开放接口,修复上游同步不对的问题
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m55s
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m55s
This commit is contained in:
@@ -2,9 +2,12 @@ package logger
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
@@ -28,6 +31,89 @@ func truncateBody(body []byte, maxSize int) string {
|
||||
return string(body[:maxSize]) + "... (truncated)"
|
||||
}
|
||||
|
||||
// maskSensitiveValue 按字段名判断并脱敏访问日志中的敏感值
|
||||
func maskSensitiveValue(key, value string) string {
|
||||
if value == "" {
|
||||
return value
|
||||
}
|
||||
normalized := strings.ToLower(key)
|
||||
if strings.Contains(normalized, "password") ||
|
||||
strings.Contains(normalized, "sign") ||
|
||||
strings.Contains(normalized, "nonce") ||
|
||||
strings.Contains(normalized, "token") ||
|
||||
strings.Contains(normalized, "secret") {
|
||||
return "***"
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// sanitizeQuery 脱敏 query 中的密码、签名、nonce、token 等字段
|
||||
func sanitizeQuery(rawQuery string) string {
|
||||
if rawQuery == "" {
|
||||
return ""
|
||||
}
|
||||
values, err := url.ParseQuery(rawQuery)
|
||||
if err != nil {
|
||||
return rawQuery
|
||||
}
|
||||
for key, items := range values {
|
||||
for index, item := range items {
|
||||
items[index] = maskSensitiveValue(key, item)
|
||||
}
|
||||
values[key] = items
|
||||
}
|
||||
return values.Encode()
|
||||
}
|
||||
|
||||
// sanitizeBody 脱敏 JSON 请求体后再写入访问日志
|
||||
func sanitizeBody(rawBody []byte) string {
|
||||
if len(rawBody) == 0 {
|
||||
return ""
|
||||
}
|
||||
var payload any
|
||||
if err := sonic.Unmarshal(rawBody, &payload); err != nil {
|
||||
return truncateBody(rawBody, MaxBodyLogSize)
|
||||
}
|
||||
sanitizeJSONValue(payload)
|
||||
data, err := sonic.Marshal(payload)
|
||||
if err != nil {
|
||||
return truncateBody(rawBody, MaxBodyLogSize)
|
||||
}
|
||||
return truncateBody(data, MaxBodyLogSize)
|
||||
}
|
||||
|
||||
// sanitizeJSONValue 递归脱敏 JSON 对象中的敏感字段
|
||||
func sanitizeJSONValue(value any) {
|
||||
switch typed := value.(type) {
|
||||
case map[string]any:
|
||||
for key, item := range typed {
|
||||
if masked, ok := item.(string); ok {
|
||||
typed[key] = maskSensitiveValue(key, masked)
|
||||
continue
|
||||
}
|
||||
if shouldMaskField(key) {
|
||||
typed[key] = "***"
|
||||
continue
|
||||
}
|
||||
sanitizeJSONValue(item)
|
||||
}
|
||||
case []any:
|
||||
for _, item := range typed {
|
||||
sanitizeJSONValue(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// shouldMaskField 判断字段名是否属于访问日志敏感字段
|
||||
func shouldMaskField(key string) bool {
|
||||
normalized := strings.ToLower(key)
|
||||
return strings.Contains(normalized, "password") ||
|
||||
strings.Contains(normalized, "sign") ||
|
||||
strings.Contains(normalized, "nonce") ||
|
||||
strings.Contains(normalized, "token") ||
|
||||
strings.Contains(normalized, "secret")
|
||||
}
|
||||
|
||||
// Middleware 创建 Fiber 日志中间件
|
||||
// 记录所有 HTTP 请求到访问日志(包括请求和响应 body)
|
||||
func Middleware() fiber.Handler {
|
||||
@@ -50,10 +136,10 @@ func Middleware() fiber.Handler {
|
||||
c.SetUserContext(ctx)
|
||||
|
||||
// 获取请求 body(在 c.Next() 之前读取)
|
||||
requestBody := truncateBody(c.Body(), MaxBodyLogSize)
|
||||
requestBody := sanitizeBody(c.Body())
|
||||
|
||||
// 获取 query 参数
|
||||
queryParams := string(c.Request().URI().QueryString())
|
||||
queryParams := sanitizeQuery(string(c.Request().URI().QueryString()))
|
||||
|
||||
// 处理请求
|
||||
err := c.Next()
|
||||
|
||||
Reference in New Issue
Block a user