JWT令牌
- 创业
- 2025-08-29 05:48:02

目录
一、JWT
1、什么是JWT
2、JWT的组成
3、JJWT签发与验证token
1、创建token
2、解析token
3、设置过期时间
4、自定义claims
前言:
在现代Web应用和微服务架构中,用户身份验证和信息安全传输是核心问题。JSON Web Token(JWT)作为一种轻量级的认证机制,已成为开发者解决这些问题的重要工具。通过它,系统可以实现无状态认证,不需要在服务器端存储会话信息,既提高了性能,又增强了可扩展性。本文将介绍JWT的基本概念、组成部分以及它的token令牌的生成与校验。
一、JWT 1、什么是JWTJWT(JSON Web Token)是一种开放标准(RFC 7519),用于在网络应用环境中作为紧凑的、独立的方式安全地传递信息。JWT通常用于用户身份验证和信息交换,尤其是在Web应用和微服务架构中。
2、JWT的组成头部(Header):通常包含两部分信息,算法类型(如HMAC SHA256或RSA)以及令牌的类型(通常是JWT)。
头部用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等。这也可以被表示成一个JSON对象。
{"typ":"JWT","alg":"HS256"}
在头部指明了签名算法是HS256算法。 我们进行BASE64编码http://base64.xpcha /,编码后的字符串如下:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9
负载(Payload):包含声明(Claims)。声明是关于实体(通常是用户)以及额外数据的信息。声明有三种类型:
注册声明:这些是JWT规范中推荐的标准声明,如iss(签发者)、exp(过期时间)、sub(主题)等。公共声明:可以自由定义的声明,但需要避免冲突。私有声明:是JWT中双方自行约定的声明,用于传递应用程序自定义信息。用白话说负载就是存放有效信息的地方。
定义一个payload:
{"sub":"1234567890","name":"John Doe","admin":true}
然后将其进行base64加密,得到Jwt的第二部分。
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
签名(Signature):为了确保JWT的安全性,使用头部和负载部分,再加上一个密钥,按照头部中指定的签名算法(如HMAC SHA256)生成签名。这个签名可以验证消息是否在传输过程中被篡改过。
jwt的第三部分是一个签证信息,这个签证信息由三部分组成:
header (base64后的)
payload (base64后的)
secret
这个部分需要base64加密后的header和base64加密后的payload使用.连接组成的字符串,然后通过header中声明的加密方式进行加盐secret组合加密,然后就构成了jwt的第三部分。
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
将这三部分用.连接成一个完整的字符串,构成了最终的jwt:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
JWT的主要优势是其自包含性,信息可以存储在令牌内部,服务器不需要保存会话信息,从而提高了可扩展性和性能。
3、JJWT签发与验证tokenJJWT是一个提供端到端的JWT创建和验证的Java库。永远免费和开源(Apache License,版本2.0),JJWT很容易使用和理解。它被设计成一个以建筑为中心的流畅界面,隐藏了它的大部分复杂性。
1、创建token首先要在项目的pom文件中添加依赖,如下:
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
接下来创建测试类,代码如下
JwtBuilder builder= Jwts.builder() .setId("888") //设置唯一编号 .setSubject("小白")//设置主题 可以是JSON数据 .setIssuedAt(new Date())//设置签发日期 .signWith(SignatureAlgorithm.HS256,"java");//设置签名 使用HS256算法,并设置SecretKey(字符串) //构建 并返回一个字符串 System.out.println( builder pact() );运行打印结果:
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NTc5MDQxODF9.ThecMfgYjtoys3JX7dpx3hu6pUm0piZ0tXXreFU_u3Y
再次运行,会发现每次运行的结果是不一样的,因为我们的载荷中包含了时间。
2、解析token我们刚才已经创建了token ,在web应用中这个操作是由服务端进行然后发给客户端,客户端在下次向服务端发送请求时需要携带这个token(这就好像是拿着一张门票一样),那服务端接到这个token 应该解析出token中的信息(例如用户id),根据这些信息查询数据库返回相应的结果。
String compactJwt="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NTc5MDQxODF9.ThecMfgYjtoys3JX7dpx3hu6pUm0piZ0tXXreFU_u3Y"; Claims claims = Jwts.parser().setSigningKey("java").parseClaimsJws(compactJwt).getBody(); System.out.println(claims);运行打印效果:
{jti=888, sub=小白, iat=1557904181}
试着将token或签名秘钥篡改一下,会发现运行时就会报错,所以解析token也就是验证token。
3、设置过期时间有很多时候,我们并不希望签发的token是永久生效的,所以我们可以为token添加一个过期时间。
创建token 并设置过期时间:
//当前时间 long currentTimeMillis = System.currentTimeMillis(); Date date = new Date(currentTimeMillis); JwtBuilder builder= Jwts.builder() .setId("888") //设置唯一编号 .setSubject("小白")//设置主题 可以是JSON数据 .setIssuedAt(new Date())//设置签发日期 .setExpiration(date) .signWith(SignatureAlgorithm.HS256,"java");//设置签名 使用HS256算法,并设置SecretKey(字符串) //构建 并返回一个字符串 System.out.println( builder pact() );解释:
.setExpiration(date)//用于设置过期时间 ,参数为Date类型数据
运行,打印效果如下:
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NTc5MDUzMDgsImV4cCI6MTU1NzkwNTMwOH0.4q5AaTyBRf8SB9B3Tl-I53PrILGyicJC3fgR3gWbvUI
解析TOKEN:
String compactJwt="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NTc5MDUzMDgsImV4cCI6MTU1NzkwNTMwOH0.4q5AaTyBRf8SB9B3Tl-I53PrILGyicJC3fgR3gWbvUI"; Claims claims = Jwts.parser().setSigningKey("java").parseClaimsJws(compactJwt).getBody(); System.out.println(claims);打印结果:
当前时间超过过期时间,则会报错。
4、自定义claims我们刚才的例子只是存储了id和subject两个信息,如果你想存储更多的信息(例如角色)可以定义自定义claims。
创建测试类,并设置测试方法:
创建token:
@Test public void createJWT(){ //当前时间 long currentTimeMillis = System.currentTimeMillis(); currentTimeMillis+=1000000L; Date date = new Date(currentTimeMillis); JwtBuilder builder= Jwts.builder() .setId("888") //设置唯一编号 .setSubject("小白")//设置主题 可以是JSON数据 .setIssuedAt(new Date())//设置签发日期 .setExpiration(date)//设置过期时间 .claim("roles","admin")//设置角色 .signWith(SignatureAlgorithm.HS256,"java");//设置签名 使用HS256算法,并设置SecretKey(字符串) //构建 并返回一个字符串 System.out.println( builder pact() ); }运行打印效果:
eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NTc5MDU4MDIsImV4cCI6MTU1NzkwNjgwMiwicm9sZXMiOiJhZG1pbiJ9.AS5Y2fNCwUzQQxXh_QQWMpaB75YqfuK-2P7VZiCXEJI
解析TOKEN:
//解析 @Test public void parseJWT(){ String compactJwt="eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI4ODgiLCJzdWIiOiLlsI_nmb0iLCJpYXQiOjE1NTc5MDU4MDIsImV4cCI6MTU1NzkwNjgwMiwicm9sZXMiOiJhZG1pbiJ9.AS5Y2fNCwUzQQxXh_QQWMpaB75YqfuK-2P7VZiCXEJI"; Claims claims = Jwts.parser().setSigningKey("java").parseClaimsJws(compactJwt).getBody(); System.out.println(claims); }运行效果:
下一篇
qsort介绍与实现