feat: 添加日志管理和敏感词过滤功能

- 新增日志管理模块:操作日志、登录日志、数据变更日志
- 新增敏感词过滤器 (sanitizer)
- 新增日志异步写入管理器
- 新增日志定时清理服务
- 优化帖子相关服务和上传服务
This commit is contained in:
2026-03-15 02:25:10 +08:00
parent d3065b30cc
commit ebd9cb8b04
31 changed files with 2753 additions and 60 deletions

View File

@@ -0,0 +1,139 @@
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
}