PII(Personally Identifiable Information,个人身份信息)自动脱敏是 aster 的安全功能,可以在将消息发送到 LLM 之前自动检测并脱敏敏感信息,防止数据泄漏。
PIIEmail): 如 user@example.comPIIPhone): 如 (555) 123-4567PIIChinesePhone): 如 13812345678PIIIPAddress): 如 192.168.1.1PIIDateOfBirth): 如 1990-01-01PIICreditCard): 支持 Visa、MasterCard、Amex 等
PIISSNus): 如 123-45-6789PIIChineseID): 18位身份证号
PIIPassport): 通用格式package main
import (
"github.com/astercloud/aster/pkg/security"
"github.com/astercloud/aster/pkg/agent"
)
func main() {
// 使用默认配置
piiMiddleware := security.NewDefaultPIIMiddleware()
// 创建 Agent 并添加中间件
agent := agent.NewAgent(agent.Config{
Name: "my-agent",
})
agent.AddMiddleware(piiMiddleware)
}
// 创建检测器
detector := security.NewRegexPIIDetector()
// 选择脱敏策略
strategy := security.NewAdaptiveStrategy() // 自适应策略
// 配置中间件
piiMiddleware := security.NewPIIRedactionMiddleware(security.PIIMiddlewareConfig{
Detector: detector,
Strategy: strategy,
EnableTracking: true, // 启用 PII 追踪
Priority: 200, // 中间件优先级
})
部分掩码,保留部分信息以供识别:
strategy := security.NewMaskStrategy()
// 邮箱: john.doe@example.com -> j*******@example.com
// 电话: 13812345678 -> 138****5678
// 信用卡: 4532148803436464 -> 4532********6464
配置选项:
strategy := &security.MaskStrategy{
MaskChar: '*', // 掩码字符
KeepPrefix: 3, // 保留前缀长度
KeepSuffix: 4, // 保留后缀长度
MinMaskLength: 4, // 最小掩码长度
}
完全替换为类型标签:
strategy := security.NewReplaceStrategy()
// 邮箱: user@example.com -> [EMAIL]
// 电话: 13812345678 -> [CHINESE_PHONE]
// 信用卡: 4532148803436464 -> [CREDIT_CARD]
自定义标签:
strategy := &security.ReplaceStrategy{
UseTypeLabel: true,
CustomLabels: map[security.PIIType]string{
security.PIIEmail: "[用户邮箱]",
security.PIIChinesePhone: "[手机号]",
},
}
使用 SHA256 单向加密:
strategy := security.NewHashStrategy()
// 任何 PII -> [HASH:a3f58b1d...]
配置选项:
strategy := &security.HashStrategy{
ShowPrefix: true,
PrefixLength: 8,
Salt: "your-secret-salt", // 生产环境使用随机盐值
}
根据敏感度自动选择策略:
strategy := security.NewAdaptiveStrategy()
// 低敏感(如邮箱) -> MaskStrategy
// 中等敏感(如电话) -> MaskStrategy
// 高敏感(如信用卡) -> ReplaceStrategy
自定义策略:
strategy := &security.AdaptiveStrategy{
LowStrategy: security.NewMaskStrategy(),
MediumStrategy: security.NewMaskStrategy(),
HighStrategy: security.NewReplaceStrategy(),
}
启用追踪后,可以查看检测到的 PII 信息:
// 启用追踪
piiMiddleware := security.NewPIIRedactionMiddleware(security.PIIMiddlewareConfig{
EnableTracking: true,
// ...
})
// 获取 PII 匹配记录
matches := piiMiddleware.GetPIIMatches("agent-id")
for _, match := range matches {
fmt.Printf("检测到 %s: %s (置信度: %.2f, 敏感度: %d)\n",
match.Type, match.Value, match.Confidence, match.Severity)
}
// 获取 PII 摘要
summary := piiMiddleware.GetPIISummary("agent-id")
fmt.Printf("检测到 %d 个 PII\n", summary.TotalMatches)
fmt.Printf("最高风险级别: %d\n", summary.HighestRisk)
for piiType, count := range summary.TypeCounts {
fmt.Printf(" %s: %d 个\n", piiType, count)
}
// 清除追踪信息
piiMiddleware.ClearTracking("agent-id")
根据上下文条件决定是否脱敏:
// 创建条件中间件
conditionalMw := security.NewConditionalPIIMiddleware(security.ConditionalPIIConfig{
Detector: security.NewRegexPIIDetector(),
Strategy: security.NewAdaptiveStrategy(),
Condition: func(ctx context.Context, req *middleware.ModelRequest) bool {
// 只对特定 Agent 脱敏
if req.Metadata != nil {
if agentType, ok := req.Metadata["agent_type"].(string); ok {
return agentType == "public-facing"
}
}
return false
},
})
import "regexp"
// 添加自定义模式
customPattern := security.PIIPattern{
Type: security.PIICustom,
Description: "Employee ID",
Regex: regexp.MustCompile(`\bEMP-\d{6}\b`),
Validator: func(value string) bool {
// 自定义验证逻辑
return len(value) == 10
},
}
security.AddCustomPattern(customPattern)
detector := security.NewRegexPIIDetector()
// 只检测邮箱和电话
matches, err := detector.DetectTypes(ctx, text,
security.PIIEmail,
security.PIIChinesePhone,
)
// 创建上下文
piiContext := &security.PIIContext{
MinConfidence: 0.8, // 最低置信度
AllowedTypes: []security.PIIType{security.PIIEmail}, // 白名单
IgnorePatterns: []string{"@company.com"}, // 忽略公司邮箱
}
// 过滤匹配结果
filtered := security.FilterMatchesByContext(matches, piiContext)
不使用中间件,直接脱敏文本:
detector := security.NewRegexPIIDetector()
strategy := security.NewMaskStrategy()
redactor := security.NewRedactor(detector, strategy)
// 简单脱敏
redacted, err := redactor.Redact(ctx, "My phone is 13812345678")
// -> "My phone is 138****5678"
// 带报告的脱敏
redacted, report, err := redactor.RedactWithReport(ctx, text)
fmt.Printf("脱敏了 %d 个字符\n", report.RedactedCharacters)
fmt.Printf("共 %d 个匹配\n", report.TotalMatches)
EnableTracking: false// 客服 Agent 处理用户咨询,需要脱敏用户信息
piiMiddleware := security.NewPIIRedactionMiddleware(security.PIIMiddlewareConfig{
Detector: security.NewRegexPIIDetector(),
Strategy: security.NewAdaptiveStrategy(), // 根据敏感度自适应
EnableTracking: true, // 启用追踪用于审计
Priority: 100, // 高优先级
})
// 内部 Agent 不需要严格脱敏,使用条件脱敏
conditionalMw := security.NewConditionalPIIMiddleware(security.ConditionalPIIConfig{
Detector: security.NewRegexPIIDetector(),
Strategy: security.NewMaskStrategy(), // 仅掩码
Condition: func(ctx context.Context, req *middleware.ModelRequest) bool {
// 只脱敏外部 API 调用
return req.Metadata["external_api"] == true
},
})
// 严格合规,完全替换所有 PII
piiMiddleware := security.NewPIIRedactionMiddleware(security.PIIMiddlewareConfig{
Detector: security.NewRegexPIIDetector(),
Strategy: security.NewReplaceStrategy(), // 完全替换
EnableTracking: true,
Priority: 50, // 最高优先级
})
运行 PII 脱敏测试:
go test ./pkg/security/ -v