You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

137 lines
3.3 KiB

  1. package middleware
  2. import (
  3. "errors"
  4. "gin-vue-admin/config"
  5. "gin-vue-admin/controller/servers"
  6. "gin-vue-admin/model/sysModel"
  7. "github.com/dgrijalva/jwt-go"
  8. "github.com/gin-gonic/gin"
  9. uuid "github.com/satori/go.uuid"
  10. "time"
  11. )
  12. func JWTAuth() gin.HandlerFunc {
  13. return func(c *gin.Context) {
  14. // 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localSstorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
  15. token := c.Request.Header.Get("x-token")
  16. ModelToken := sysModel.JwtBlacklist{
  17. Jwt: token,
  18. }
  19. if token == "" {
  20. servers.ReportFormat(c, false, "未登录或非法访问", gin.H{
  21. "reload": true,
  22. })
  23. c.Abort()
  24. return
  25. }
  26. if ModelToken.IsBlacklist(token) {
  27. servers.ReportFormat(c, false, "授权已失效", gin.H{
  28. "reload": true,
  29. })
  30. c.Abort()
  31. return
  32. }
  33. j := NewJWT()
  34. // parseToken 解析token包含的信息
  35. claims, err := j.ParseToken(token)
  36. if err != nil {
  37. if err == TokenExpired {
  38. servers.ReportFormat(c, false, "授权已过期", gin.H{
  39. "reload": true,
  40. })
  41. c.Abort()
  42. return
  43. }
  44. servers.ReportFormat(c, false, err.Error(), gin.H{
  45. "reload": true,
  46. })
  47. c.Abort()
  48. return
  49. }
  50. c.Set("claims", claims)
  51. c.Next()
  52. }
  53. }
  54. type JWT struct {
  55. SigningKey []byte
  56. }
  57. var (
  58. TokenExpired error = errors.New("Token is expired")
  59. TokenNotValidYet error = errors.New("Token not active yet")
  60. TokenMalformed error = errors.New("That's not even a token")
  61. TokenInvalid error = errors.New("Couldn't handle this token:")
  62. )
  63. type CustomClaims struct {
  64. UUID uuid.UUID
  65. ID uint
  66. NickName string
  67. AuthorityId string
  68. jwt.StandardClaims
  69. }
  70. func NewJWT() *JWT {
  71. return &JWT{
  72. []byte(config.GinVueAdminconfig.JWT.SigningKey),
  73. }
  74. }
  75. //创建一个token
  76. func (j *JWT) CreateToken(claims CustomClaims) (string, error) {
  77. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  78. return token.SignedString(j.SigningKey)
  79. }
  80. //解析 token
  81. func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) {
  82. token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) {
  83. return j.SigningKey, nil
  84. })
  85. if err != nil {
  86. if ve, ok := err.(*jwt.ValidationError); ok {
  87. if ve.Errors&jwt.ValidationErrorMalformed != 0 {
  88. return nil, TokenMalformed
  89. } else if ve.Errors&jwt.ValidationErrorExpired != 0 {
  90. // Token is expired
  91. return nil, TokenExpired
  92. } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
  93. return nil, TokenNotValidYet
  94. } else {
  95. return nil, TokenInvalid
  96. }
  97. }
  98. }
  99. if token != nil {
  100. if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
  101. return claims, nil
  102. }
  103. return nil, TokenInvalid
  104. } else {
  105. return nil, TokenInvalid
  106. }
  107. }
  108. // 更新token
  109. func (j *JWT) RefreshToken(tokenString string) (string, error) {
  110. jwt.TimeFunc = func() time.Time {
  111. return time.Unix(0, 0)
  112. }
  113. token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
  114. return j.SigningKey, nil
  115. })
  116. if err != nil {
  117. return "", err
  118. }
  119. if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
  120. jwt.TimeFunc = time.Now
  121. claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix()
  122. return j.CreateToken(*claims)
  123. }
  124. return "", TokenInvalid
  125. }