auth_middleware.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package utils
  2. import (
  3. "fmt"
  4. "github.com/beego/beego/v2/server/web/context"
  5. )
  6. // AuthMiddleware Token认证中间件
  7. func AuthMiddleware(ctx *context.Context) {
  8. // ============ 最优先:立即打印,证明中间件被调用 ============
  9. fmt.Printf("\n\n🚀🚀🚀🚀🚀 [AUTH中间件] 开始执行!\n")
  10. fmt.Printf(" 请求方法: %s\n", ctx.Request.Method)
  11. fmt.Printf(" 请求路径: %s\n", ctx.Request.URL.Path)
  12. fmt.Printf(" 完整URL: %s\n", ctx.Request.URL.String())
  13. // 添加一个 defer 来捕获任何 panic
  14. defer func() {
  15. if r := recover(); r != nil {
  16. fmt.Printf("❌❌❌ [中间件] 发生panic: %v\n", r)
  17. }
  18. }()
  19. // 跳过某些不需要认证的路由
  20. skipPaths := []string{
  21. "/stream-test",
  22. "/simple-stream-test",
  23. "/stream-chat-with-db-test",
  24. "/assets/",
  25. "/static/",
  26. "/src/",
  27. }
  28. // 特殊处理:精确匹配根路径 "/"
  29. if ctx.Request.URL.Path == "/" {
  30. fmt.Printf("⏭️ [中间件] 跳过路径: / (根路径)\n\n")
  31. return
  32. }
  33. // 检查其他跳过路径
  34. for _, path := range skipPaths {
  35. // 精确匹配或前缀匹配(对于目录路径)
  36. if ctx.Request.URL.Path == path || (len(ctx.Request.URL.Path) > len(path) && ctx.Request.URL.Path[:len(path)] == path) {
  37. fmt.Printf("⏭️ [中间件] 跳过路径: %s (匹配规则: %s)\n\n", ctx.Request.URL.Path, path)
  38. return
  39. }
  40. }
  41. // 对于API请求,验证token
  42. if len(ctx.Request.URL.Path) >= 6 && ctx.Request.URL.Path[:6] == "/apiv1" {
  43. // 打印所有请求头,帮助调试
  44. fmt.Printf("\n========== Token认证中间件 ==========\n")
  45. fmt.Printf("📍 请求路径: %s\n", ctx.Request.URL.Path)
  46. fmt.Printf("📋 所有请求头:\n")
  47. for key, values := range ctx.Request.Header {
  48. fmt.Printf(" %s: %v\n", key, values)
  49. }
  50. // 获取token - 添加详细的调试信息
  51. fmt.Printf("\n🔍 开始提取Token:\n")
  52. token1 := ctx.Input.Header("token")
  53. fmt.Printf(" 尝试 'token': %s (长度: %d)\n", token1, len(token1))
  54. token2 := ctx.Input.Header("Token")
  55. fmt.Printf(" 尝试 'Token': %s (长度: %d)\n", token2, len(token2))
  56. token3 := ctx.Input.Header("Authorization")
  57. fmt.Printf(" 尝试 'Authorization': %s (长度: %d)\n", token3, len(token3))
  58. // 确定最终使用的token
  59. token := token1
  60. if token == "" {
  61. token = token2
  62. }
  63. if token == "" {
  64. token = token3
  65. // 如果是Bearer token格式,去掉"Bearer "前缀
  66. if len(token) > 7 && token[:7] == "Bearer " {
  67. oldToken := token
  68. token = token[7:]
  69. fmt.Printf(" 去除Bearer前缀: %s -> %s\n", oldToken[:20]+"...", token[:20]+"...")
  70. }
  71. }
  72. fmt.Printf("\n🔑 最终提取到的Token: %s (长度: %d)\n", token, len(token))
  73. // 如果没有token,返回401
  74. if token == "" {
  75. fmt.Printf("❌❌❌ Token为空,拒绝请求\n")
  76. fmt.Printf("❌ 原因:请求头中没有找到 token、Token 或 Authorization 字段\n")
  77. fmt.Printf("=====================================\n\n")
  78. ctx.Output.SetStatus(401)
  79. ctx.Output.JSON(map[string]interface{}{
  80. "statusCode": 401,
  81. "msg": "未提供认证token,请在请求头中添加 token 字段",
  82. }, false, false)
  83. return
  84. }
  85. // 验证token
  86. userInfo, err := VerifyToken(token)
  87. if err != nil {
  88. fmt.Printf("❌❌❌ Token验证失败: %v\n", err)
  89. fmt.Printf("❌ Token内容: %s\n", token)
  90. fmt.Printf("❌ 请检查token是否正确或已过期\n")
  91. fmt.Printf("=====================================\n\n")
  92. ctx.Output.SetStatus(401)
  93. ctx.Output.JSON(map[string]interface{}{
  94. "statusCode": 401,
  95. "msg": fmt.Sprintf("token验证失败: %v", err),
  96. }, false, false)
  97. return
  98. }
  99. // 打印解析出的用户信息
  100. fmt.Printf("✅ Token验证成功,解析出的用户信息:\n")
  101. fmt.Printf(" - AccountID: %s\n", userInfo.AccountID)
  102. fmt.Printf(" - ID: %d\n", userInfo.ID)
  103. fmt.Printf(" - Name: %s\n", userInfo.Name)
  104. fmt.Printf(" - UserCode: %s\n", userInfo.UserCode)
  105. fmt.Printf(" - ContactNumber: %s\n", userInfo.ContactNumber)
  106. fmt.Printf(" - TokenType: %s\n", userInfo.TokenType)
  107. // 将用户信息存储到context中,供后续handler使用
  108. fmt.Printf("\n💾 [中间件] 将用户信息存储到context中...\n")
  109. fmt.Printf(" 存储的指针地址: %p\n", userInfo)
  110. fmt.Printf(" 存储的值: %+v\n", userInfo)
  111. ctx.Input.SetData("userInfo", userInfo)
  112. // 验证是否存储成功
  113. storedData := ctx.Input.GetData("userInfo")
  114. fmt.Printf(" 验证存储: %T, 值=%+v\n", storedData, storedData)
  115. fmt.Printf("=====================================\n\n")
  116. } else {
  117. fmt.Printf("⏭️ [中间件] 非API路径,不需要token验证: %s\n\n", ctx.Request.URL.Path)
  118. }
  119. }