13.JWT
# 01.JWT介绍
# 1.1 什么是JWT?
- JWT全称JSON Web Token是一种跨域认证解决方案,属于一个开放的标准,它规定了一种Token实现方式
- 目前多用于前后端分离项目和OAuth2.0业务场景下。
# 1.2 jwt三部分
- 基于JWT技术及RSA非对称加密实现真正无状态的单点登录
# 02.JWT基本用法
# 2.1 定义需求
- 我们需要定制自己的需求来决定JWT中保存哪些数据
- 比如我们规定在JWT中要存储
username
信息 - 那么我们就定义一个
MyClaims
结构体如下
// MyClaims 自定义声明结构体并内嵌jwt.StandardClaims
// jwt包自带的jwt.StandardClaims只包含了官方字段
// 我们这里需要额外记录一个username字段,所以要自定义结构体
// 如果想要保存更多信息,都可以添加到这个结构体中
type MyClaims struct {
Username string `json:"username"`
jwt.StandardClaims
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- 然后我们定义JWT的过期时间,这里以2小时为例:
const TokenExpireDuration = time.Hour * 2
1
- 接下来还需要定义Secret:
var MySecret = []byte("夏天夏天悄悄过去")
1
# 2.2 生成JWT
// GenToken 生成JWT
func GenToken(username string) (string, error) {
// 创建一个我们自己的声明
c := MyClaims{
username, // 自定义字段
jwt.StandardClaims{
ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间
Issuer: "my-project", // 签发人
},
}
// 使用指定的签名方法创建签名对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
// 使用指定的secret签名并获得完整的编码后的字符串token
return token.SignedString(MySecret)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 2.3 解析JWT
// ParseToken 解析JWT
func ParseToken(tokenString string) (*MyClaims, error) {
// 解析token
token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (i interface{}, err error) {
return MySecret, nil
})
if err != nil {
return nil, err
}
if claims, ok := token.Claims.(*MyClaims); ok && token.Valid { // 校验token
return claims, nil
}
return nil, errors.New("invalid token")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 03.项目使用JWT
# 3.1 pkg/jwt/jwt.go
package jwt
import (
"errors"
"github.com/dgrijalva/jwt-go"
"time"
)
const TokenExpireDuration = time.Hour * 2
var mySecret = []byte("夏天夏天悄悄过去")
// MyClaims 自定义声明结构体并内嵌jwt.StandardClaims
// jwt包自带的jwt.StandardClaims只包含了官方字段
// 我们这里需要额外记录一个username字段,所以要自定义结构体
// 如果想要保存更多信息,都可以添加到这个结构体中
type MyClaims struct {
UserID int64 `json:"user_id"`
Username string `json:"username"`
jwt.StandardClaims
}
// GenToken 生成JWT
func GenToken(userID int64, username string) (string, error) {
// 创建一个我们自己的声明的数据
c := MyClaims{
userID,
"username", // 自定义字段
jwt.StandardClaims{
ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(), // 过期时间
Issuer: "bluebell", // 签发人
},
}
// 使用指定的签名方法创建签名对象
token := jwt.NewWithClaims(jwt.SigningMethodHS256, c)
// 使用指定的secret签名并获得完整的编码后的字符串token
return token.SignedString(mySecret)
}
// ParseToken 解析JWT
func ParseToken(tokenString string) (*MyClaims, error) {
// 解析token
var mc = new(MyClaims)
token, err := jwt.ParseWithClaims(tokenString, mc, func(token *jwt.Token) (i interface{}, err error) {
return mySecret, nil
})
if err != nil {
return nil, err
}
if token.Valid { // 校验token
return mc, nil
}
return nil, errors.New("invalid token")
}
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
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
# 3.2 在controllers模块中调用
上次更新: 2024/3/13 15:35:10