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.

130 lines
3.1 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. c.Abort()
  17. return
  18. }
  19. j := NewJWT()
  20. // parseToken 解析token包含的信息
  21. claims, err := j.ParseToken(token)
  22. if err != nil {
  23. if err == TokenExpired {
  24. servers.ReportFormat(c, false, "授权已过期", gin.H{})
  25. c.Abort()
  26. return
  27. }
  28. servers.ReportFormat(c, false, err.Error(), gin.H{})
  29. c.Abort()
  30. return
  31. }
  32. c.Set("claims", claims)
  33. }
  34. }
  35. type JWT struct {
  36. SigningKey []byte
  37. }
  38. var (
  39. TokenExpired error = errors.New("Token is expired")
  40. TokenNotValidYet error = errors.New("Token not active yet")
  41. TokenMalformed error = errors.New("That's not even a token")
  42. TokenInvalid error = errors.New("Couldn't handle this token:")
  43. SignKey string = "qmPlus"
  44. )
  45. type CustomClaims struct {
  46. UUID uuid.UUID
  47. ID uint
  48. NickName string
  49. AuthorityId float64
  50. jwt.StandardClaims
  51. }
  52. func NewJWT() *JWT {
  53. return &JWT{
  54. []byte(GetSignKey()),
  55. }
  56. }
  57. //获取token
  58. func GetSignKey() string {
  59. return SignKey
  60. }
  61. // 这是SignKey
  62. func SetSignKey(key string) string {
  63. SignKey = key
  64. return SignKey
  65. }
  66. //创建一个token
  67. func (j *JWT) CreateToken(claims CustomClaims) (string, error) {
  68. token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
  69. return token.SignedString(j.SigningKey)
  70. }
  71. //解析 token
  72. func (j *JWT) ParseToken(tokenString string) (*CustomClaims, error) {
  73. token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (i interface{}, e error) {
  74. return j.SigningKey, nil
  75. })
  76. if err != nil {
  77. if ve, ok := err.(*jwt.ValidationError); ok {
  78. if ve.Errors&jwt.ValidationErrorMalformed != 0 {
  79. return nil, TokenMalformed
  80. } else if ve.Errors&jwt.ValidationErrorExpired != 0 {
  81. // Token is expired
  82. return nil, TokenExpired
  83. } else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
  84. return nil, TokenNotValidYet
  85. } else {
  86. return nil, TokenInvalid
  87. }
  88. }
  89. }
  90. if token != nil {
  91. if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
  92. return claims, nil
  93. }
  94. return nil, TokenInvalid
  95. } else {
  96. return nil, TokenInvalid
  97. }
  98. }
  99. // 更新token
  100. func (j *JWT) RefreshToken(tokenString string) (string, error) {
  101. jwt.TimeFunc = func() time.Time {
  102. return time.Unix(0, 0)
  103. }
  104. token, err := jwt.ParseWithClaims(tokenString, &CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
  105. return j.SigningKey, nil
  106. })
  107. if err != nil {
  108. return "", err
  109. }
  110. if claims, ok := token.Claims.(*CustomClaims); ok && token.Valid {
  111. jwt.TimeFunc = time.Now
  112. claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix()
  113. return j.CreateToken(*claims)
  114. }
  115. return "", TokenInvalid
  116. }