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