- 新增日志管理模块:操作日志、登录日志、数据变更日志 - 新增敏感词过滤器 (sanitizer) - 新增日志异步写入管理器 - 新增日志定时清理服务 - 优化帖子相关服务和上传服务
140 lines
3.3 KiB
Go
140 lines
3.3 KiB
Go
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
|
||
}
|