首页IT科技java-jwt包作用(Java中JWT的使用)

java-jwt包作用(Java中JWT的使用)

时间2025-08-05 01:43:34分类IT科技浏览5282
导读:JWT简介 JWT全称为Json Web Token...

JWT简介

JWT全称为Json Web Token

JWT的本质就是一个字符串                ,它是将用户信息保存到一个Json字符串中                          ,然后进行编码后得到一个JWT token        ,并且这个JWT token带有签名信息            ,接收后可以校验是否被篡改                          ,所以可以用于在各方之间安全地将信息作为Json对象传输                  。

JWT的认证流程如下:

1 首先            ,前端通过Web表单将自己的用户名和密码发送到后端的接口        ,这个过程一般是一个POST请求                        。建议的方式是通过SSL加密的传输(HTTPS)                          ,从而避免敏感信息被嗅探

2 后端核对用户名和密码成功后                 ,将包含用户信息的数据作为JWT的Payload    ,将其与JWT Header分别进行Base64编码后拼接签名                         ,形成一个JWT Token                      ,形成的JWT Token就是一个如同lll.zzz.xxx的字符串

3 后端将JWT Token字符串作为登录成功的结果返回给前端        。前端可以将返回的结果保存在浏览器中,退出登录时删除保存的JWT Token即可

4 前端在每次请求时将JWT Token放入HTTP请求头中的Authorization属性中(解决XSS和XSRF问题)

5 后端检查前端传过来的JWT Token                    ,验证其有效性                          ,比如检查签名是否正确                  、是否过期                        、token的接收方是否是自己等等

6 验证通过后    ,后端解析出JWT Token中包含的用户信息                ,进行其他逻辑操作(一般是根据用户信息得到权限等)                          ,返回结果

JWT结构

JWT由3部分组成:标头(header)        、有效载荷(payLoad)              、签名(signature)

              。

在传输的时候        ,会将JWT的3部分分别进行Base64编码后用.连接形成最终传输的字符串                        。

Header

JWT头是一个描述JWT元数据的JSON对象            ,alg属性表示签名使用的算法                          ,默认为HMAC SHA256(写为HS256);typ属性表示令牌的类型            ,JWT令牌统一写为JWT            。最后        ,使用Base64 URL算法将上述JSON对象转换为字符串保存

{ "alg": "HS256", "typ": "JWT" }

PayLoad

有效载荷部分                          ,是JWT的主体内容部分                 ,也是一个JSON对象    ,包含需要传递的数据          。 JWT指定七个默认字段供选择

iss:发行人 exp:到期时间 sub:主题 aud:用户 nbf:在此之前不可用 iat:发布时间 jti:JWT ID用于标识该JWT

除以上默认字段外                         ,我们还可以自定义私有字段                      ,一般会把包含用户信息的数据放到payload中,如下

{ "id": "123", "name": "cheng" }

Signature

签名哈希部分是对上面两部分数据签名                    ,需要使用base64编码后的header和payload数据                          ,通过指定的算法生成哈希    ,以确保数据不会被篡改                         。首先                ,需要指定一个密钥(secret)                。该密码仅仅为保存在服务器中                          ,并且不能向用户公开     。然后        ,使用header中指定的签名算法(默认情况下为HMAC SHA256)根据以下公式生成签名

HMACSHA256(base64UrlEncode(header)+"."+base64UrlEncode(payload),secret)

在计算出签名哈希后            ,JWT头                          ,有效载荷和签名哈希的三个部分组合成一个字符串            ,每个部分用.分隔        ,就构成整个JWT对象

注意JWT每部分的作用                          ,在服务端接收到客户端发送过来的JWT token之后:

header和payload可以直接利用base64解码出原文                 ,从header中获取哈希签名的算法    ,从payload中获取有效数据

signature由于使用了不可逆的加密算法                         ,无法解码出原文                      ,它的作用是校验token有没有被篡改                          。服务端获取header中的加密算法之后,利用该算法加上secretKey对header                        、payload进行加密                    ,比对加密后的数据和客户端发送过来的是否一致                    。

为了完成签名                          ,除了用到header信息和payload信息外    ,还需要算法的密钥                ,也就是secretKey。加密的算法一般有2类:

对称加密:secretKey指加密密钥                          ,可以生成签名与验签 非对称加密:secretKey指私钥        ,只用来生成签名            ,不能用来验签(验签用的是公钥)

JWT的密钥或者密钥对                          ,一般统一称为JSON Web Key            ,也就是JWK

到目前为止        ,jwt的签名算法有三种: HMAC【哈希消息验证码(对称)】:HS256/HS384/HS512 RSASSA【RSA签名算法(非对称)】(RS256/RS384/RS512) ECDSA【椭圆曲线数据签名算法(非对称)】(ES256/ES384/ES512)

Java中使用JWT

我这里用的是java-jwt

引入依赖

<dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.10.3</version> </dependency>

对称签名

生成JWT的Token /** * 生成JWT token */ @Test void generateToken(){ //预设一个token过期时间 Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.HOUR,1);//过期时间为1小时 String token = JWT.create() .withHeader(new HashMap<>())//Header .withClaim("userId", 123)//PayLoad .withClaim("userName", "程") .withClaim("userId1", "456") .withExpiresAt(calendar.getTime())//过期时间 .sign(Algorithm.HMAC256("12345"));//签名用的密钥secret System.out.println(token); }

利用base64解密工具来查看生成的JWT Token中header和payLoad的明文

解析JWT字符串 /** * 解析jwt字符串 */ @Test void resolveToken(){ String token = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWRJbnQiOjEyMywidXNlcklkU3RyaW5nIjoiNDU2IiwidXNlck5hbWUiOiLnqIsiLCJleHAiOjE2NzU5MTQzMDZ9.MNC-YCxt8C0t9SNbj3_XMRknkK3-PKBP5xX6_JLB8y8"; //创建解析对象                          ,使用的算法和secret要和创建token时保持一致 JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256("12345")).build(); DecodedJWT decodedJWT = jwtVerifier.verify(token); System.out.println(decodedJWT.getPayload());//base64编码的payLoad Claim userIdInt = decodedJWT.getClaim("userIdInt"); Claim userIdString = decodedJWT.getClaim("userIdString"); Claim userName = decodedJWT.getClaim("userName"); System.out.println("userIdInt:"+userIdInt.asInt()); System.out.println("userIdString:"+userIdString.asString()); System.out.println("userName:"+userName.asString()); System.out.println("过期时间:"+new LocalDateTime(decodedJWT.getExpiresAt())); }

如果我们设置的token时间短                 ,比如设置为1秒

那么解析时为抛出如下异常

非对称签名

private static final String RSA_PRIVATE_KEY = "..."; private static final String RSA_PUBLIC_KEY = "..."; /** * 生成token * @param payload token携带的信息 * @return token字符串 */ public static String getTokenRsa(Map<String,String> payload){ // 指定token过期时间为7天 Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.DATE, 7); JWTCreator.Builder builder = JWT.create(); // 构建payload payload.forEach((k,v) -> builder.withClaim(k,v)); // 利用hutool创建RSA RSA rsa = new RSA(RSA_PRIVATE_KEY, null); // 获取私钥 RSAPrivateKey privateKey = (RSAPrivateKey) rsa.getPrivateKey(); // 签名时传入私钥 String token = builder.withExpiresAt(calendar.getTime()).sign(Algorithm.RSA256(null, privateKey)); return token; } /** * 解析token * @param token token字符串 * @return 解析后的token */ public static DecodedJWT decodeRsa(String token){ // 利用hutool创建RSA RSA rsa = new RSA(null, RSA_PUBLIC_KEY); // 获取RSA公钥 RSAPublicKey publicKey = (RSAPublicKey) rsa.getPublicKey(); // 验签时传入公钥 JWTVerifier jwtVerifier = JWT.require(Algorithm.RSA256(publicKey, null)).build(); DecodedJWT decodedJWT = jwtVerifier.verify(token); return decodedJWT; }

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
python中不可变的数据类型(Python的高级特性:容易忽略的不可变类型)