Files
backend/internal/pkg/sanitizer/sanitizer.go
lan ebd9cb8b04 feat: 添加日志管理和敏感词过滤功能
- 新增日志管理模块:操作日志、登录日志、数据变更日志
- 新增敏感词过滤器 (sanitizer)
- 新增日志异步写入管理器
- 新增日志定时清理服务
- 优化帖子相关服务和上传服务
2026-03-15 02:25:10 +08:00

140 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package sanitizer
import (
"strings"
)
// SensitiveFields 敏感字段列表
var SensitiveFields = []string{
"password", " Password", "pwd",
"token", "access_token", "refresh_token", "Token",
"secret", "Secret", "api_key", "apiKey", "secret_key",
"id_card", "idCard", "身份证",
"phone", "mobile", "Phone", "Mobile", "手机号",
"email", "Email", "邮箱",
"bank_card", "bankCard", "银行卡",
"credit_card", "信用卡",
"address", "Address", "详细地址",
"real_name", "realName", "真实姓名",
}
// SkipMaskFields 不需要脱敏的字段
var SkipMaskFields = []string{
"avatar", "nickname", "username", "content", "title", "description",
}
// MaskValue 根据字段名脱敏处理
func MaskValue(field, value string) string {
if value == "" {
return ""
}
fieldLower := strings.ToLower(field)
// 检查是否跳过脱敏
for _, f := range SkipMaskFields {
if fieldLower == f || strings.HasSuffix(fieldLower, f) {
return value
}
}
// 根据字段类型脱敏
switch {
case strings.Contains(fieldLower, "phone"):
return maskPhone(value)
case strings.Contains(fieldLower, "email"):
return maskEmail(value)
case strings.Contains(fieldLower, "id_card"):
return maskIDCard(value)
case strings.Contains(fieldLower, "bank_card") || strings.Contains(fieldLower, "credit_card"):
return maskBankCard(value)
case strings.Contains(fieldLower, "token") || strings.Contains(fieldLower, "secret") || strings.Contains(fieldLower, "api_key"):
return "***"
case fieldLower == "password" || fieldLower == "pwd":
return "***"
case strings.Contains(fieldLower, "address"):
return maskAddress(value)
case strings.Contains(fieldLower, "real_name"):
return maskName(value)
default:
return value
}
}
// maskPhone 手机号脱敏保留前3后4
func maskPhone(s string) string {
if len(s) == 11 {
return s[:3] + "****" + s[7:]
}
return "***"
}
// maskEmail 邮箱脱敏保留前2
func maskEmail(s string) string {
parts := strings.Split(s, "@")
if len(parts) == 2 && len(parts[0]) > 2 {
return parts[0][:2] + "***@" + parts[1]
}
return "***"
}
// maskIDCard 身份证脱敏保留前6后4
func maskIDCard(s string) string {
if len(s) == 18 {
return s[:6] + "********" + s[14:]
}
if len(s) == 15 {
return s[:6] + "*****" + s[11:]
}
return "***"
}
// maskBankCard 银行卡号脱敏保留前4后4
func maskBankCard(s string) string {
length := len(s)
if length >= 8 {
return s[:4] + "****" + s[length-4:]
}
return "***"
}
// maskAddress 地址脱敏(只显示省市)
func maskAddress(s string) string {
parts := strings.Split(s, "省")
if len(parts) > 1 {
cityParts := strings.Split(parts[1], "市")
if len(cityParts) > 1 {
return parts[0] + "省" + cityParts[0] + "市****"
}
return parts[0] + "省****"
}
return "***"
}
// maskName 姓名脱敏(保留姓氏)
func maskName(s string) string {
runes := []rune(s)
length := len(runes)
if length == 0 {
return ""
}
if length == 2 {
return string(runes[0]) + "*"
}
if length >= 3 {
return string(runes[0]) + "*" + string(runes[length-1:])
}
return "*"
}
// IsSensitiveField 判断字段是否为敏感字段
func IsSensitiveField(field string) bool {
fieldLower := strings.ToLower(field)
for _, f := range SensitiveFields {
if strings.Contains(fieldLower, f) {
return true
}
}
return false
}