package logger import ( "time" "github.com/gin-gonic/gin" "go.uber.org/zap" ) // AuditMiddleware 创建审计中间件 func AuditMiddleware(audit AuditLogger, logger Logger) gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() // 获取用户信息(这里需要根据你的认证系统调整) userID := getUserID(c) username := getUsername(c) // 处理请求 c.Next() // 计算请求持续时间 duration := time.Since(start) // 记录访问日志 logger.Info("HTTP请求", zap.String("method", c.Request.Method), zap.String("path", c.Request.URL.Path), zap.String("query", c.Request.URL.RawQuery), zap.String("ip", c.ClientIP()), zap.String("user_agent", c.Request.UserAgent()), zap.Int("status", c.Writer.Status()), zap.Duration("duration", duration), zap.String("user_id", userID), ) // 记录审计事件 entry := &AuditEntry{ UserID: userID, Username: username, Action: c.Request.Method + " " + c.Request.URL.Path, Resource: c.Request.URL.Path, Details: c.Request.URL.RawQuery, IP: c.ClientIP(), UserAgent: c.Request.UserAgent(), Success: c.Writer.Status() < 400, } // 如果有错误,记录错误信息 if len(c.Errors) > 0 { entry.Error = c.Errors.String() entry.Success = false } // 异步记录审计,避免阻塞请求 go func() { if err := audit.Record(entry); err != nil { // 审计失败记录到日志,但不影响正常业务 logger.Error("审计记录失败", zap.Error(err)) } }() } } // RequestLogger 创建请求日志中间件(不包含审计) func RequestLogger(logger Logger) gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() // 处理请求 c.Next() // 计算请求持续时间 duration := time.Since(start) // 记录请求日志 logger.Info("HTTP请求", zap.String("method", c.Request.Method), zap.String("path", c.Request.URL.Path), zap.String("query", c.Request.URL.RawQuery), zap.String("ip", c.ClientIP()), zap.String("user_agent", c.Request.UserAgent()), zap.Int("status", c.Writer.Status()), zap.Duration("duration", duration), ) } } // RecoveryMiddleware 创建恢复中间件 func RecoveryMiddleware(logger Logger) gin.HandlerFunc { return gin.CustomRecovery(func(c *gin.Context, recovered interface{}) { if err, ok := recovered.(string); ok { logger.Error("panic recovered", zap.String("error", err), zap.String("method", c.Request.Method), zap.String("path", c.Request.URL.Path), zap.String("ip", c.ClientIP()), ) } else { logger.Error("panic recovered", zap.Any("error", recovered), zap.String("method", c.Request.Method), zap.String("path", c.Request.URL.Path), zap.String("ip", c.ClientIP()), ) } c.AbortWithStatusJSON(500, gin.H{ "error": "Internal Server Error", }) }) } // getUserID 从请求上下文中获取用户ID // 这里需要根据你的认证系统进行调整 func getUserID(c *gin.Context) string { // 示例:从JWT token或session中获取 if userID, exists := c.Get("user_id"); exists { if id, ok := userID.(string); ok { return id } } return "" } // getUsername 从请求上下文中获取用户名 // 这里需要根据你的认证系统进行调整 func getUsername(c *gin.Context) string { // 示例:从JWT token或session中获取 if username, exists := c.Get("username"); exists { if name, ok := username.(string); ok { return name } } return "" } // AuditHelper 审计助手,提供便捷的审计方法 type AuditHelper struct { audit AuditLogger logger Logger } // NewAuditHelper 创建审计助手 func NewAuditHelper(audit AuditLogger, logger Logger) *AuditHelper { return &AuditHelper{ audit: audit, logger: logger, } } // RecordLogin 记录登录事件 func (h *AuditHelper) RecordLogin(userID, username, ip, userAgent string, success bool) { entry := &AuditEntry{ UserID: userID, Username: username, Action: "login", Resource: "auth", IP: ip, UserAgent: userAgent, Success: success, } if err := h.audit.Record(entry); err != nil { h.logger.Error("记录登录审计失败", zap.Error(err)) } } // RecordUserAction 记录用户操作 func (h *AuditHelper) RecordUserAction(userID, username, action, resource, resourceID, ip string, success bool) { entry := &AuditEntry{ UserID: userID, Username: username, Action: action, Resource: resource, Details: resourceID, IP: ip, Success: success, } if err := h.audit.Record(entry); err != nil { h.logger.Error("记录用户操作审计失败", zap.Error(err)) } } // RecordSystemEvent 记录系统事件 func (h *AuditHelper) RecordSystemEvent(event, details string) { entry := &AuditEntry{ Action: "system_event", Resource: event, Details: details, Success: true, } if err := h.audit.Record(entry); err != nil { h.logger.Error("记录系统事件审计失败", zap.Error(err)) } }