暂无描述
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

basic_auth_middewara.go 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package authbase
  2. import (
  3. "encoding/base64"
  4. "net/http"
  5. "strings"
  6. "time"
  7. "git.x2erp.com/qdy/go-base/config"
  8. "git.x2erp.com/qdy/go-base/ctx"
  9. "git.x2erp.com/qdy/go-base/logger"
  10. )
  11. // BasicAuth 简化的Basic认证中间件
  12. func BasicAuth(next http.Handler) http.Handler {
  13. return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  14. if logger.IsDebug() {
  15. logger.Debug("BasicAuth中间件开始处理请求: %s %s", r.Method, r.URL.Path)
  16. }
  17. // 1. 检查认证头
  18. authHeader := r.Header.Get("Authorization")
  19. if authHeader == "" {
  20. if logger.IsDebug() {
  21. logger.Debug("认证头缺失,请求未授权: %s %s", r.Method, r.URL.Path)
  22. }
  23. unauthorized(w, "缺少认证信息")
  24. return
  25. }
  26. if logger.IsDebug() {
  27. displayHeader := authHeader
  28. if len(displayHeader) > 20 {
  29. displayHeader = displayHeader[:20] + "..."
  30. }
  31. logger.Debug("收到认证头: %s", displayHeader)
  32. }
  33. // 2. 检查Basic格式
  34. if !strings.HasPrefix(authHeader, "Basic ") {
  35. if logger.IsDebug() {
  36. displayHeader := authHeader
  37. if len(displayHeader) > 20 {
  38. displayHeader = displayHeader[:20] + "..."
  39. }
  40. logger.Debug("认证格式错误,需要Basic认证: %s", displayHeader)
  41. }
  42. unauthorized(w, "认证格式错误,请使用Basic认证")
  43. return
  44. }
  45. // 3. 解码凭证
  46. base64Creds := strings.TrimPrefix(authHeader, "Basic ")
  47. if logger.IsDebug() {
  48. logger.Debug("解码Base64凭证,长度: %d", len(base64Creds))
  49. }
  50. credsBytes, err := base64.StdEncoding.DecodeString(base64Creds)
  51. if err != nil {
  52. if logger.IsDebug() {
  53. logger.Debug("Base64解码失败: %v", err)
  54. }
  55. unauthorized(w, "认证信息解码失败")
  56. return
  57. }
  58. // 4. 分割用户名密码
  59. creds := string(credsBytes)
  60. if logger.IsDebug() {
  61. logger.Debug("解码后凭证长度: %d", len(creds))
  62. }
  63. parts := strings.SplitN(creds, ":", 2)
  64. if len(parts) != 2 {
  65. if logger.IsDebug() {
  66. logger.Debug("用户名密码格式错误,分割后部分数: %d", len(parts))
  67. }
  68. unauthorized(w, "用户名密码格式错误")
  69. return
  70. }
  71. username := parts[0]
  72. password := parts[1]
  73. if logger.IsDebug() {
  74. logger.Debug("提取用户名: %s,密码长度: %d", username, len(password))
  75. }
  76. // 5. 验证用户名密码
  77. if logger.IsDebug() {
  78. logger.Debug("开始验证用户名密码: %s", username)
  79. }
  80. userID, tenantID, ok := verifyCredentials(username, password)
  81. if !ok {
  82. if logger.IsDebug() {
  83. logger.Debug("用户名密码验证失败: %s", username)
  84. }
  85. unauthorized(w, "用户名或密码错误")
  86. return
  87. }
  88. if logger.IsDebug() {
  89. logger.Debug("用户名密码验证成功: userID=%s, tenantID=%s", userID, tenantID)
  90. }
  91. // 6. 创建请求上下文
  92. traceID := r.Header.Get("X-Trace-ID")
  93. if traceID == "" {
  94. // 生成简单的时间戳追踪ID
  95. traceID = time.Now().Format("20060102150405.000")
  96. if logger.IsDebug() {
  97. logger.Debug("生成TraceID: %s", traceID)
  98. }
  99. } else if logger.IsDebug() {
  100. logger.Debug("使用请求中的TraceID: %s", traceID)
  101. }
  102. cfg := config.GetConfig()
  103. requestCtx := &ctx.RequestContext{
  104. ServiceName: cfg.GetServiceConfig().ServiceName,
  105. InstanceName: cfg.GetServiceConfig().InstanceName,
  106. TraceID: traceID,
  107. TenantID: tenantID,
  108. UserID: userID,
  109. Username: username,
  110. }
  111. if logger.IsDebug() {
  112. logger.Debug("创建请求上下文: service=%s, instance=%s, tenant=%s, user=%s",
  113. requestCtx.ServiceName, requestCtx.InstanceName, requestCtx.TenantID, requestCtx.UserID)
  114. }
  115. // 7. 保存到请求
  116. r = ctx.SaveContext(r, requestCtx)
  117. // 8. 继续处理
  118. if logger.IsDebug() {
  119. logger.Debug("BasicAuth中间件处理完成,继续下一个处理器")
  120. }
  121. next.ServeHTTP(w, r)
  122. })
  123. }
  124. // 验证用户名密码(简单示例)
  125. func verifyCredentials(username, password string) (userID, tenantID string, ok bool) {
  126. if logger.IsDebug() {
  127. logger.Debug("验证凭据,用户名: %s", username)
  128. }
  129. // 这里替换为你的实际验证逻辑
  130. cfg := config.GetConfig()
  131. sysUsername := cfg.GetServiceConfig().Username
  132. sysPassword := cfg.GetServiceConfig().Password
  133. if username == sysUsername && password == sysPassword {
  134. if logger.IsDebug() {
  135. logger.Debug("凭据验证成功,用户名匹配系统用户")
  136. }
  137. return sysUsername, "tenant-admin", true
  138. }
  139. if logger.IsDebug() {
  140. logger.Debug("凭据验证失败,用户名或密码不匹配")
  141. }
  142. return "", "", false
  143. }