JWT在Java中的使用

  • Post author:
  • Post category:java




一、概述



JSON Web Token (JWT) 是一个开放标准 (

RFC 7519

),它定义了一种紧凑且自包含的方式,用于在各方之间作为 JSON 对象安全地传输信息。该信息可以被验证和信任,因为它是经过数字签名的。JWT 可以使用秘密(使用

HMAC

算法)或使用

RSA



ECDSA

的公钥/私钥对进行

签名




虽然 JWT 可以加密以在各方之间提供保密,但我们将重点关注

签名

令牌。签名令牌可以验证其中包含的声明的

完整性

,而加密令牌则对其他方

隐藏

这些声明。当使用公钥/私钥对对令牌进行签名时,签名还证明只有持有私钥的一方才是对其进行签名的一方。




二、使用场景





授权




这是使用 JWT 最常见的场景。用户登录后,每个后续请求都将包含 JWT,允许用户访问该令牌允许的路由、服务和资源。单点登录是现在广泛使用 JWT 的一项功能,因为它的开销很小,并且能够轻松地跨不同域使用。



信息交换




JSON Web Tokens 是一种在各方之间安全传输信息的好方法。因为 JWT 可以被签名——例如,使用公钥/私钥对——你可以确定发件人就是他们所说的那样。此外,由于使用标头和有效负载计算签名,因此您还可以验证内容是否未被篡改。

三、JWT结构



在其紧凑形式中,JSON Web Tokens 由用点 (

.

)分隔的三个部分组成,它们是:


标题

默认情况下标头

通常

由两部分组成:令牌的类型,即 JWT,以及正在使用的签名算法,例如 HMAC SHA256 或 RSA,也可以在默认的类型和签名算法添加新的信息。

默认生成的头部信息,alg根据使用的签名算法自动生成。

{


“alg”: “HS256”,

“typ”: “JWT”

}

可在默认头部信息外添加新的信息

//默认之外添加的新的头部信息
Map<String, Object> stringStringHashMap = new HashMap<>();
stringStringHashMap.put("type","jwt");
stringStringHashMap.put("name","test");
stringStringHashMap.put("time",
        TimestampUtils.getTimestamp(new Date()));
//测试负载部分的数组
Long[] id = new Long[]{1L,2L,3L};
//生成jwt负载信息
String sign = JWT.create()
        //头部信息
        .withHeader(stringStringHashMap)
        //有效载荷
        .withClaim("t1", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t2", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t3", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t4", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t5", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t6", TimestampUtils.getTimestamp(new Date()))
        .withArrayClaim("id", id)
        //签名
        .sign(hhhh);


有效载荷



令牌的第二部分是负载,说白了就是我们要放用户的一些非敏感信息。

//默认之外添加的新的头部信息
Map<String, Object> stringStringHashMap = new HashMap<>();
stringStringHashMap.put("type","jwt");
stringStringHashMap.put("name","test");
stringStringHashMap.put("time",
        TimestampUtils.getTimestamp(new Date()));
//测试负载部分的数组
Long[] id = new Long[]{1L,2L,3L};
//生成jwt负载信息
String sign = JWT.create()
        //头部信息
        .withHeader(stringStringHashMap)
        //有效载荷
        .withClaim("t1", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t2", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t3", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t4", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t5", TimestampUtils.getTimestamp(new Date()))
        .withClaim("t6", TimestampUtils.getTimestamp(new Date()))
        .withArrayClaim("id", id)
        //签名
        .sign(hhhh);



签名


要创建签名部分,必须获取jwt的头部、有效载荷、密钥加上指定的算法,并对其进行签名。



因此,JWT 通常如下所示。




xxxxx.yyyyy.zzzzz




eyJuYW1lIjoidGVzdCIsInR5cCI6IkpXVCIsInRpbWUiOjE2Mjg0MjMxOTUzOTUsInR5cGUiOiJqd3QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6WzEsMiwzXX0.s5_2UOEvNvd-n3mjB8fIzW0sqwlvLG9xqTGVbF5651M



四、实例演示




jwt的依赖


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


代码


package com.test.Utils;

import com.auth0.jwt.JWT;

import com.auth0.jwt.JWTVerifier;

import com.auth0.jwt.algorithms.Algorithm;

import com.auth0.jwt.exceptions.AlgorithmMismatchException;

import com.auth0.jwt.exceptions.InvalidClaimException;

import com.auth0.jwt.exceptions.SignatureVerificationException;

import com.auth0.jwt.exceptions.TokenExpiredException;

import com.auth0.jwt.interfaces.Claim;

import com.auth0.jwt.interfaces.DecodedJWT;

import org.apache.commons.codec.binary.Base64;

import java.util.Date;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

public class JwtUtils {


private static final String pwd = “123456”;

//生成jwtToken

public static String CreateToken(){


//签名使用的密钥

Algorithm hhhh = Algorithm.HMAC256(pwd);

//生成jwt头部信息

/**

* 如果不添加头部信息,默认会把添加

* {


*   “typ”: “JWT”,

*   “alg”: “加密类型”

* }

*/

Map<String, Object> stringStringHashMap = new HashMap<>();

stringStringHashMap.put(“type”,”jwt”);

stringStringHashMap.put(“name”,”test”);

stringStringHashMap.put(“time”,

TimestampUtils.getTimestamp(new Date()));

//测试负载部分的数组

Long[] id = new Long[]{1L,2L,3L};

//生成jwt负载信息

String sign = JWT.create()

.withHeader(stringStringHashMap)

.withClaim(“t1”, TimestampUtils.getTimestamp(new Date()))

.withClaim(“t2”, TimestampUtils.getTimestamp(new Date()))

.withClaim(“t3”, TimestampUtils.getTimestamp(new Date()))

.withClaim(“t4”, TimestampUtils.getTimestamp(new Date()))

.withClaim(“t5”, TimestampUtils.getTimestamp(new Date()))

.withClaim(“t6”, TimestampUtils.getTimestamp(new Date()))

.withArrayClaim(“id”, id)

.sign(hhhh);

return sign;

}

//验证jwt

public static void verify(String jwtStr){


JWTVerifier build = JWT.require(Algorithm.HMAC256(pwd)).build();

try{


//验签

DecodedJWT verify = build.verify(jwtStr);

System.out.println(“完整的token”);

System.out.println(verify.getToken());

System.out.println(“头部信息”);

System.out.println(verify.getHeader());

System.out.println(“负荷信息”);

System.out.println(verify.getPayload());

System.out.println(“签名信息”);

System.out.println(verify.getSignature());

//获取主体对应信息

System.out.println(“获取主体对应信息”);

byte[] bytes = Base64.decodeBase64(verify.getPayload());

System.out.println(new String(bytes));

System.out.println(“获取头部信息”);

byte[] bytes1 = Base64.decodeBase64(verify.getHeader());

System.out.println(new String(bytes1));

System.out.println(“获取签名信息”);

byte[] bytes2 = Base64.decodeBase64(verify.getSignature());

System.out.println(new String(bytes2));


//获取所有负荷信息中的所有Claims

System.out.println(“获取所有负荷信息中的所有Claims”);

Map<String, Claim> claims = verify.getClaims();

//

Iterator<Map.Entry<String, Claim>> iterator = claims.entrySet().iterator();

//遍历

while (iterator.hasNext()) {


Map.Entry<String, Claim> next = iterator.next();

System.out.println(next.getKey()+”:”+next.getValue().asLong());

}

//获取头部信息

System.out.println(verify.getHeaderClaim(“typ”).asString());

}

catch (AlgorithmMismatchException e){


//算法错误

System.out.println(“加密算法和解密算法不一致”);

}

catch (SignatureVerificationException e){


//验签失败,验签pwd密码错误

System.out.println(“解密密码错误”);

}

catch (TokenExpiredException e){


//token过期

System.out.println(“Token过期”);

}

catch (InvalidClaimException e){


//获取不到对应的负荷信息

System.out.println(“获取不到对应的负荷信息”);

}

}

public static void main(String[] args) {


String token = CreateToken();

System.out.println(token);

verify(token);

}

}

五、jwt官网地址


https://jwt.io/introduction



版权声明:本文为qq_42838143原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。