jwt.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package controller
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strconv"
  6. "time"
  7. "woord-core-service/global"
  8. "github.com/gin-gonic/gin"
  9. "github.com/golang-jwt/jwt/v4"
  10. )
  11. const (
  12. AuthUserKey = "_user"
  13. AuthTokenKey = "_token"
  14. )
  15. var (
  16. ErrNotLoggedIn = fmt.Errorf("请先登录")
  17. ErrInvalidToken = fmt.Errorf("登录失效,请重新登录")
  18. )
  19. // 根据用户 ID 生成 JWT
  20. func newToken(userID uint) (string, error) {
  21. token := jwt.NewWithClaims(jwt.SigningMethodHS256, &jwt.RegisteredClaims{
  22. Subject: strconv.FormatUint(uint64(userID), 10),
  23. ExpiresAt: jwt.NewNumericDate(time.Now().Add(720 * time.Hour)),
  24. })
  25. return token.SignedString(global.SecretKey)
  26. }
  27. // 根据 JWT 解析用户 ID
  28. func parseToken(tokenString string) (uint, error) {
  29. token, err := jwt.ParseWithClaims(tokenString, &jwt.RegisteredClaims{}, func(token *jwt.Token) (any, error) {
  30. // 检查签名方法是否正确
  31. if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
  32. return nil, fmt.Errorf("unexpected signing method: %s", token.Method.Alg())
  33. }
  34. return global.SecretKey, nil
  35. })
  36. if claims, ok := token.Claims.(*jwt.RegisteredClaims); ok && token.Valid {
  37. userID, err := strconv.ParseUint(claims.Subject, 10, 0)
  38. return uint(userID), err
  39. }
  40. return 0, err
  41. }
  42. // JWT 认证中间件
  43. func JWTAuth() gin.HandlerFunc {
  44. return func(c *gin.Context) {
  45. // 从 Cookie 获取 JWT
  46. token, err := c.Cookie(AuthTokenKey)
  47. if err != nil {
  48. respondError(c, http.StatusUnauthorized, ErrNotLoggedIn)
  49. c.Abort()
  50. return
  51. }
  52. // 解析 JWT
  53. userID, err := parseToken(token)
  54. if err != nil {
  55. respondError(c, http.StatusUnauthorized, ErrInvalidToken)
  56. c.Abort()
  57. return
  58. }
  59. // 将用户 ID 保存在上下文中
  60. c.Set(AuthUserKey, userID)
  61. }
  62. }