auth_middleware.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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. "/apiv1/oss/parse", // OSS代理解析接口,用于图片/文件资源访问,不需要token认证
  28. }
  29. // 特殊处理:精确匹配根路径 "/"
  30. if ctx.Request.URL.Path == "/" {
  31. fmt.Printf("⏭️ [中间件] 跳过路径: / (根路径)\n\n")
  32. return
  33. }
  34. // 检查其他跳过路径
  35. for _, path := range skipPaths {
  36. // 精确匹配或前缀匹配(对于目录路径)
  37. if ctx.Request.URL.Path == path || (len(ctx.Request.URL.Path) > len(path) && ctx.Request.URL.Path[:len(path)] == path) {
  38. fmt.Printf("⏭️ [中间件] 跳过路径: %s (匹配规则: %s)\n\n", ctx.Request.URL.Path, path)
  39. return
  40. }
  41. }
  42. // 对于API请求,验证token
  43. if len(ctx.Request.URL.Path) >= 6 && ctx.Request.URL.Path[:6] == "/apiv1" {
  44. // 打印所有请求头,帮助调试
  45. fmt.Printf("\n========== Token认证中间件 ==========\n")
  46. fmt.Printf("📍 请求路径: %s\n", ctx.Request.URL.Path)
  47. fmt.Printf("📋 所有请求头:\n")
  48. for key, values := range ctx.Request.Header {
  49. fmt.Printf(" %s: %v\n", key, values)
  50. }
  51. // 获取token - 添加详细的调试信息
  52. fmt.Printf("\n🔍 开始提取Token:\n")
  53. token1 := ctx.Input.Header("token")
  54. fmt.Printf(" 尝试 'token': %s (长度: %d)\n", token1, len(token1))
  55. token2 := ctx.Input.Header("Token")
  56. fmt.Printf(" 尝试 'Token': %s (长度: %d)\n", token2, len(token2))
  57. token3 := ctx.Input.Header("Authorization")
  58. fmt.Printf(" 尝试 'Authorization': %s (长度: %d)\n", token3, len(token3))
  59. // 确定最终使用的token
  60. token := token1
  61. if token == "" {
  62. token = token2
  63. }
  64. if token == "" {
  65. token = token3
  66. // 如果是Bearer token格式,去掉"Bearer "前缀
  67. if len(token) > 7 && token[:7] == "Bearer " {
  68. oldToken := token
  69. token = token[7:]
  70. fmt.Printf(" 去除Bearer前缀: %s -> %s\n", oldToken[:20]+"...", token[:20]+"...")
  71. }
  72. }
  73. fmt.Printf("\n🔑 最终提取到的Token: %s (长度: %d)\n", token, len(token))
  74. // 如果没有token,返回401
  75. if token == "" {
  76. fmt.Printf("❌❌❌ Token为空,拒绝请求\n")
  77. fmt.Printf("❌ 原因:请求头中没有找到 token、Token 或 Authorization 字段\n")
  78. fmt.Printf("=====================================\n\n")
  79. ctx.Output.SetStatus(401)
  80. ctx.Output.JSON(map[string]interface{}{
  81. "statusCode": 401,
  82. "msg": "未提供认证token,请在请求头中添加 token 字段",
  83. }, false, false)
  84. return
  85. }
  86. // 验证token
  87. userInfo, err := VerifyToken(token)
  88. if err != nil {
  89. fmt.Printf("❌❌❌ Token验证失败: %v\n", err)
  90. fmt.Printf("❌ Token内容: %s\n", token)
  91. fmt.Printf("❌ 请检查token是否正确或已过期\n")
  92. fmt.Printf("=====================================\n\n")
  93. ctx.Output.SetStatus(401)
  94. ctx.Output.JSON(map[string]interface{}{
  95. "statusCode": 401,
  96. "msg": fmt.Sprintf("token验证失败: %v", err),
  97. }, false, false)
  98. return
  99. }
  100. // 打印解析出的用户信息
  101. fmt.Printf("✅ Token验证成功,解析出的用户信息:\n")
  102. fmt.Printf(" - AccountID: %s\n", userInfo.AccountID)
  103. fmt.Printf(" - ID: %d\n", userInfo.ID)
  104. fmt.Printf(" - Name: %s\n", userInfo.Name)
  105. fmt.Printf(" - UserCode: %s\n", userInfo.UserCode)
  106. fmt.Printf(" - ContactNumber: %s\n", userInfo.ContactNumber)
  107. fmt.Printf(" - TokenType: %s\n", userInfo.TokenType)
  108. // 将用户信息存储到context中,供后续handler使用
  109. fmt.Printf("\n💾 [中间件] 将用户信息存储到context中...\n")
  110. fmt.Printf(" 存储的指针地址: %p\n", userInfo)
  111. fmt.Printf(" 存储的值: %+v\n", userInfo)
  112. ctx.Input.SetData("userInfo", userInfo)
  113. // 验证是否存储成功
  114. storedData := ctx.Input.GetData("userInfo")
  115. fmt.Printf(" 验证存储: %T, 值=%+v\n", storedData, storedData)
  116. fmt.Printf("=====================================\n\n")
  117. } else {
  118. fmt.Printf("⏭️ [中间件] 非API路径,不需要token验证: %s\n\n", ctx.Request.URL.Path)
  119. }
  120. }