这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记
1. 什么是JWT
JWT(JSON Web Token),简单理解可以看作是一个字符串,由三个部分组成,分别是HEADER,PAYLOAD,SIGNATURE,用·将三个部分分隔。
- HEADER
HEADER一般有两个字段,一个是alg(signing algorithm),一般为HMAC SHA256或者RSA,另一个是typ(type of the token),内容是JWT,这个部分经过Base64编码得到JWT的第一个部分。
- PAYLOAD
PAYLOAD包含claims,claims是一个实体的声明和附加信息。可以包含如用户信息和过期时间等,这个部分经过Base64编码得到JWT的第二个部分。
- SIGNATURE
SIGNATURE使用一个签名算法,将用·隔开的经过Base64编码的前两个部分和一个密码字符串,一起生成。密码字符串存放在服务器上,不对外公开,检查这个部分,可以发现JWT是否被篡改。例如下面的例子是用HMAC SHA256算法签名。
HMACSHA256(
base64UrlEncode(header) + "." +
base64UrlEncode(payload),
secret)
这个部分经过Base64编码得到JWT的第三个部分。
我们利用JWT可以对登录用户的行为进行鉴权,这是一个开销较小的方式。
2. golang-jwt
golang-jwt是一个被广泛使用的jwt包,接下来介绍他的基本使用方式
- 定义claims和密码字符串
type MyClaims struct {
Username string `json:"username"`
jwt.StandardClaims
}
var secretKey = []byte("secret_key")
- 生成token
func GenerateToken(username string) (string, error) {
var claims MyClaims
claims.Username = username
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(secretKey)
}
- 解析token
func ParserToken(tokenString string) (*MyClaims, error) {
token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (interface{}, error) {
return secretKey, nil
})
if err != nil {
return nil, errno.ErrTokenInvalid
}
if token != nil {
if claims, ok := token.Claims.(*MyClaims); ok && token.Valid {
return claims, nil
}
return nil, errno.ErrTokenInvalid
}
return nil, errno.ErrTokenInvalid
}
3. gin-jwt
gin-jwt是一个gin的jwt扩展,他是在golang-jwt的基础上开发的。
他提供了一个LoginHandler,一个LogoutHandler,分别来处理Login request flow和Logout Request flow。还可以使用MiddlewareFunc对一些需要jwt token的子过程提供一个中间件方法的接口。