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.2 KiB

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