Web开发的身份证:JWT(json web token)令牌使用方法
				
									
					
					
						|  | 
							admin 2025年9月2日 22:43
								本文热度 1057 | 
					
				 
				先抛个问题,我们在京东购物时,整个购物过程,只登录了一次,切换页面后,为什么没有再次让你输入账号密码登录?答案就是今天的主角: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 编辑过