Web开发的身份证:JWT(json web token)令牌使用方法
|
admin
2025年9月2日 22:43
本文热度 67
|
先抛个问题,我们在京东购物时,整个购物过程,只登录了一次,切换页面后,为什么没有再次让你输入账号密码登录?答案就是今天的主角:jwt,那他又是如何实现登录态的保持呢?
JWT(JSON Web Token)是一种用于用户身份验证的机制,它保证了客户端与服务端信息的安全传输,这种传输并不是加密的传输,而是验证真伪的传输。当用户通过用户名和密码登录系统后,云端就会为此用户进行授权,为其颁发一个『身份证』:jwt,之后客户端访问云端资源,需要携带这个【身份】才能通过云端的验证,就像我们在国内带着身份证才能买机票、住酒店,拿着护照才能走遍天下,身份证、护照的验证机制就是现实版的JWT。eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IuajieiKseezliIsImlzQWRtaW4iOnRydWUsImlzcyI6IueggeWGnOWknOivuyIsInN1YiI6IuajieiKseezli1KV1Tku4vnu40iLCJhdWQiOlsicHJvZ3JhbW1lciJdLCJleHAiOjE3NTU2MTc0MzUsImlhdCI6MTc1NTUzMTAzNX0.N6uvzyo-MZqtu4A1jNt9qXcBLILVFpRt29cLNJXqNWM
- Header头部:包含令牌的类型和所使用的加密算法。
- Payload负载:实际存放的数据,可以自定义,主要有以下字段。
- Signature签名,用于验证发送者和内容是否被篡改。签名由header、payload、密钥和指定的算法生成。
下面,以一张图来展示jwt的工作流程,这样更清晰且容易理解:
- 第二个为访问云端资源时,在header中携带jwt令牌,云端对jwt进行验证后,返回对应资源。
github.com/golang-jwt/jwt/v5
var jwtKey = []byte("your_secret_key")
type Claims struct {
Username string `json:"username"`
IsAdmin bool `json:"isAdmin"`
jwt.RegisteredClaims
}
func main() {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, Claims{
Username: "棉花糖",
IsAdmin: true,
RegisteredClaims: jwt.RegisteredClaims{
Issuer: "码农夜读",
Subject: "棉花糖-JWT介绍",
Audience: []string{"programmer"},
ExpiresAt: jwt.NewNumericDate(time.Now().Add(24 * time.Hour)),
IssuedAt: jwt.NewNumericDate(time.Now()),
},
})
tokenString, err := token.SignedString(jwtKey)
if err != nil {
panic(err)
}
println("Generated Token:", tokenString)
}
jwt的合法性校验,如同校验身份证号是否准确一样,如果jwt验证通过,则可以进行下一步的资源获取,否则将会终止请求,golang-jwt包提供了对jwt进行合法性校验的api,同时当校验不通过时,也会给出明确的错误:func ValidateToken(tokenString string) (*Claims, error) {
claims := &Claims{}
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
return jwtKey, nil
})
if err != nil {
if errors.Is(err, jwt.ErrInvalidKey) {
return nil, fmt.Errorf("jwt invalid")
} else if errors.Is(err, jwt.ErrTokenMalformed) {
return nil, fmt.Errorf("malformed token")
} else if errors.Is(err, jwt.ErrTokenExpired) {
return nil, fmt.Errorf("token has expired")
}
return nil, fmt.Errorf("couldn't parse token: %v", err)
}
if !token.Valid {
return nil, fmt.Errorf("token is invalid")
}
return claims, nil
}
我们可以通过claims字段获取到生成jwt的具体内容:如果你需要校验用户id是否合法,那么就可以在生成jwt时,将用户id放入claims字段中,在解析时就可以拿到。通常,jwt的有效性校验都是放在服务中间件中,所有请求都会对jwt进行验证,以此来保证数据传输的安全。
阅读原文:原文链接
该文章在 2025/9/3 10:19:08 编辑过