新建request文件

  1. package models
  2. import "github.com/dgrijalva/jwt-go"
  3. type CustomClaims struct {
  4. ID uint
  5. NickName string
  6. AuthorityId uint
  7. jwt.StandardClaims
  8. }

生成key

https://suijimimashengcheng.bmcx.com/
image.png

编写token中间件

  1. package middlewares
  2. import (
  3. "errors"
  4. "go_final/mxshop-api/global"
  5. "go_final/mxshop-api/models"
  6. "net/http"
  7. "time"
  8. "github.com/dgrijalva/jwt-go"
  9. "github.com/gin-gonic/gin"
  10. )
  11. type JWT struct {
  12. SigningKey []byte
  13. }
  14. var (
  15. TokenExpired = errors.New("token is expired")
  16. TokenNotValidYet = errors.New("token not active yet")
  17. TokenMalformed = errors.New("that's not even a token")
  18. TokenInvalid = errors.New("couldn't handle this token")
  19. )
  20. func NewJWT() *JWT {
  21. return &JWT{
  22. []byte(global.ServerConfig.JWTInfo.SigningKey), //可以设置过期时间
  23. }
  24. }
  25. func JWTAuth() gin.HandlerFunc {
  26. return func(c *gin.Context) {
  27. // 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localSstorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
  28. token := c.Request.Header.Get("authorization")
  29. if token == "" {
  30. c.JSON(http.StatusUnauthorized, map[string]string{
  31. "msg": "请登录后操作",
  32. })
  33. c.Abort()
  34. return
  35. }
  36. j := NewJWT()
  37. // parseToken 解析token包含的信息
  38. claims, err := j.ParseToken(token)
  39. if err != nil {
  40. if err == TokenExpired {
  41. c.JSON(http.StatusUnauthorized, gin.H{
  42. "msg": "授权已过期",
  43. })
  44. c.Abort()
  45. return
  46. }
  47. c.JSON(http.StatusUnauthorized, "未登陆")
  48. c.Abort()
  49. return
  50. }
  51. c.Set("claims", claims)
  52. c.Set("userId", claims.ID)
  53. c.Next()
  54. }
  55. }
  56. // CreateToken 创建一个token
  57. func (j *JWT) CreateToken(claims models.CustomClaims) (string, error) {
  58. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  59. return token.SignedString(j.SigningKey)
  60. }
  61. // ParseToken 解析token
  62. func (j *JWT) ParseToken(tokenString string) (*models.CustomClaims, error) {
  63. token, err := jwt.ParseWithClaims(tokenString, &models.CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) {
  64. return j.SigningKey, nil
  65. })
  66. if err != nil {
  67. if ve, ok := err.(*jwt.ValidationError); ok {
  68. if ve.Errors&jwt.ValidationErrorMalformed != 0 {
  69. return nil, TokenMalformed
  70. } else if ve.Errors&jwt.ValidationErrorExpired != 0 {
  71. // Token is expired
  72. return nil, TokenExpired
  73. } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
  74. return nil, TokenNotValidYet
  75. } else {
  76. return nil, TokenInvalid
  77. }
  78. }
  79. }
  80. if token != nil {
  81. if claims, ok := token.Claims.(*models.CustomClaims); ok && token.Valid {
  82. return claims, nil
  83. }
  84. return nil, TokenInvalid
  85. } else {
  86. return nil, TokenInvalid
  87. }
  88. }
  89. // RefreshToken 更新token
  90. func (j *JWT) RefreshToken(tokenString string) (string, error) {
  91. jwt.TimeFunc = func() time.Time {
  92. return time.Unix(0, 0)
  93. }
  94. token, err := jwt.ParseWithClaims(tokenString, &models.CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
  95. return j.SigningKey, nil
  96. })
  97. if err != nil {
  98. return "", err
  99. }
  100. if claims, ok := token.Claims.(*models.CustomClaims); ok && token.Valid {
  101. jwt.TimeFunc = time.Now
  102. claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix()
  103. return j.CreateToken(*claims)
  104. }
  105. return "", TokenInvalid
  106. }

使用(生成带签名的token)

  1. jwt := middlewares.NewJWT()
  2. claims := models.CustomClaims{
  3. ID: uint(userInfo.ID),
  4. NickName: userInfo.NickName,
  5. AuthorityId: uint(userInfo.Role),
  6. StandardClaims: jwt2.StandardClaims{
  7. NotBefore: time.Now().Unix(), // 签名的生效时间
  8. ExpiresAt: time.Now().Unix() + 60*60*24*7, // 签名过期时间
  9. Issuer: "Felix_Mxshop",
  10. },
  11. }
  12. token, err := jwt.CreateToken(claims)
  13. if err != nil {
  14. // 生成token失败
  15. }