package authbase import ( "encoding/base64" "net/http" "strings" "time" "git.x2erp.com/qdy/go-base/config" "git.x2erp.com/qdy/go-base/ctx" "git.x2erp.com/qdy/go-base/logger" ) // BasicAuth 简化的Basic认证中间件 func BasicAuth(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if logger.IsDebug() { logger.Debug("BasicAuth中间件开始处理请求: %s %s", r.Method, r.URL.Path) } // 1. 检查认证头 authHeader := r.Header.Get("Authorization") if authHeader == "" { if logger.IsDebug() { logger.Debug("认证头缺失,请求未授权: %s %s", r.Method, r.URL.Path) } unauthorized(w, "缺少认证信息") return } if logger.IsDebug() { displayHeader := authHeader if len(displayHeader) > 20 { displayHeader = displayHeader[:20] + "..." } logger.Debug("收到认证头: %s", displayHeader) } // 2. 检查Basic格式 if !strings.HasPrefix(authHeader, "Basic ") { if logger.IsDebug() { displayHeader := authHeader if len(displayHeader) > 20 { displayHeader = displayHeader[:20] + "..." } logger.Debug("认证格式错误,需要Basic认证: %s", displayHeader) } unauthorized(w, "认证格式错误,请使用Basic认证") return } // 3. 解码凭证 base64Creds := strings.TrimPrefix(authHeader, "Basic ") if logger.IsDebug() { logger.Debug("解码Base64凭证,长度: %d", len(base64Creds)) } credsBytes, err := base64.StdEncoding.DecodeString(base64Creds) if err != nil { if logger.IsDebug() { logger.Debug("Base64解码失败: %v", err) } unauthorized(w, "认证信息解码失败") return } // 4. 分割用户名密码 creds := string(credsBytes) if logger.IsDebug() { logger.Debug("解码后凭证长度: %d", len(creds)) } parts := strings.SplitN(creds, ":", 2) if len(parts) != 2 { if logger.IsDebug() { logger.Debug("用户名密码格式错误,分割后部分数: %d", len(parts)) } unauthorized(w, "用户名密码格式错误") return } username := parts[0] password := parts[1] if logger.IsDebug() { logger.Debug("提取用户名: %s,密码长度: %d", username, len(password)) } // 5. 验证用户名密码 if logger.IsDebug() { logger.Debug("开始验证用户名密码: %s", username) } userID, tenantID, ok := verifyCredentials(username, password) if !ok { if logger.IsDebug() { logger.Debug("用户名密码验证失败: %s", username) } unauthorized(w, "用户名或密码错误") return } if logger.IsDebug() { logger.Debug("用户名密码验证成功: userID=%s, tenantID=%s", userID, tenantID) } // 6. 创建请求上下文 traceID := r.Header.Get("X-Trace-ID") if traceID == "" { // 生成简单的时间戳追踪ID traceID = time.Now().Format("20060102150405.000") if logger.IsDebug() { logger.Debug("生成TraceID: %s", traceID) } } else if logger.IsDebug() { logger.Debug("使用请求中的TraceID: %s", traceID) } cfg := config.GetConfig() requestCtx := &ctx.RequestContext{ ServiceName: cfg.GetServiceConfig().ServiceName, InstanceName: cfg.GetServiceConfig().InstanceName, TraceID: traceID, TenantID: tenantID, UserID: userID, Username: username, } if logger.IsDebug() { logger.Debug("创建请求上下文: service=%s, instance=%s, tenant=%s, user=%s", requestCtx.ServiceName, requestCtx.InstanceName, requestCtx.TenantID, requestCtx.UserID) } // 7. 保存到请求 r = ctx.SaveContext(r, requestCtx) // 8. 继续处理 if logger.IsDebug() { logger.Debug("BasicAuth中间件处理完成,继续下一个处理器") } next.ServeHTTP(w, r) }) } // 验证用户名密码(简单示例) func verifyCredentials(username, password string) (userID, tenantID string, ok bool) { if logger.IsDebug() { logger.Debug("验证凭据,用户名: %s", username) } // 这里替换为你的实际验证逻辑 cfg := config.GetConfig() sysUsername := cfg.GetServiceConfig().Username sysPassword := cfg.GetServiceConfig().Password if username == sysUsername && password == sysPassword { if logger.IsDebug() { logger.Debug("凭据验证成功,用户名匹配系统用户") } return sysUsername, "tenant-admin", true } if logger.IsDebug() { logger.Debug("凭据验证失败,用户名或密码不匹配") } return "", "", false }