原理
TODO
简单测试
maven 添加以下依赖:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<dependency>
<groupId> io.jsonwebtoken</groupId>
<artifactId> jjwt-api</artifactId>
<version> 0.11.2</version>
</dependency>
<dependency>
<groupId> io.jsonwebtoken</groupId>
<artifactId> jjwt-impl</artifactId>
<version> 0.11.2</version>
<scope> runtime</scope>
</dependency>
<dependency>
<groupId> io.jsonwebtoken</groupId>
<artifactId> jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
<version> 0.11.2</version>
<scope> runtime</scope>
</dependency>
encode
java code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class TempTest {
private static final Logger log = LoggerFactory . getLogger ( TempTest . class );
public static void main ( String [] args ) {
String keyStr = "Boli's blog website: https://bolitao.xyz" ;
Key jwtKey = Keys . hmacShaKeyFor ( keyStr . getBytes ( StandardCharsets . UTF_8 ));
// 自定义 header parameters
Map < String , Object > headerParams = new HashMap <>( 5 );
headerParams . put ( "kid1" , "myKeyId1" );
headerParams . put ( "kid2" , "myKeyId2" );
// 自定义 claims
Map < String , Object > claims = new HashMap <>( 5 );
claims . put ( "claimKey1" , "claimValue1" );
claims . put ( "claimKey2" , "claimValue2" );
String jws = Jwts . builder (). setSubject ( "Hello" ). setIssuedAt ( new Date ())
. setExpiration ( new Date ( System . currentTimeMillis () + 1000 ))
. setId ( String . valueOf ( UUID . randomUUID ())). addClaims ( claims )
. signWith ( jwtKey ). setHeaderParams ( headerParams ). compact ();
log . info ( jws );
}
}
output:
20:12:52.647 [main] INFO xyz.bolitao.jjwt_test.jjwt.TempTest - eyJraWQxIjoibXlLZXlJZDEiLCJraWQyIjoibXlLZXlJZDIiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJIZWxsbyIsImlhdCI6MTU5Njg4ODgzMSwiZXhwIjoxNTk2ODg4NzcxLCJqdGkiOiI2NDFkZWNlMC1kM2MzLTQ5ZmYtYTZiNy0xNDU5NmNjZDVlMGUiLCJjbGFpbUtleTEiOiJjbGFpbVZhbHVlMSIsImNsYWltS2V5MiI6ImNsYWltVmFsdWUyIn0.p0IXgzrK9yOUu4_QuKJ_0qYX5VKCL5sWEF-zATDmhJA
decode
添加以下代码:
1
log . info ( String . valueOf ( Jwts . parserBuilder (). setSigningKey ( jwtKey ). build (). parseClaimsJws ( "eyIxMjMiOiJxd2UiLCJraWQxIjoibXlLZXlJZDIxIiwia2lkMiI6Im15S2V5SWQyIiwiYWxnIjoiSFMyNTYifQ.eyJzdWIiOiJIZWwyMTMyMTMxMjNkbG8iLCJpYXQiOjE1OTY4ODk1ODQsImV4cCI6MTU5Njg5MzE4NCwianRpIjoiOTU2ZGVmM2ItNDJxd2UxZS00N2IxLWFmOTAtODRkN2FjN2NkZWIwIiwiY2xhaW1LZXkxIjoiY2xhaW1WYWx1ZTEiLCJjbGFpbUtleTIiOiJjbGFpbVZhbHVlMiJ9.Ke6mEdcWpzQCdkd_uS4T82oFgR4fM2fMwbvxSa2W2Z4" )));
输出:
20:54:00.632 [main] INFO xyz.bolitao.jjwt_test.jjwt.TempTest - header={123=qwe, kid1=myKeyId21, kid2=myKeyId2, alg=HS256},body={sub=Hel213213123dlo, iat=1596889584, exp=1596893184, jti=956def3b-42qwe1e-47b1-af90-84d7ac7cdeb0, claimKey1=claimValue1, claimKey2=claimValue2},signature=Ke6mEdcWpzQCdkd_uS4T82oFgR4fM2fMwbvxSa2W2Z4
常见错误(以下情况不该信任 token):
过期
这是一个有效期仅为 1s 的 token:
过去数秒后,使用以下代码解析:
1
log . info ( String . valueOf ( Jwts . parserBuilder (). setSigningKey ( jwtKey ). build (). parseClaimsJws ( "eyJraWQxIjoibXlLZXlJZDEiLCJraWQyIjoibXlLZXlJZDIiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJIZWxsbyIsImlhdCI6MTU5Njg5MDk5MSwiZXhwIjoxNTk2ODkwOTkyLCJqdGkiOiI2NjI2M2UxMy00ZWZmLTRlZDItODBmYS0wZjZiMzA4Njg5MTEiLCJjbGFpbUtleTEiOiJjbGFpbVZhbHVlMSIsImNsYWltS2V5MiI6ImNsYWltVmFsdWUyIn0.8YmXYlpR6OJ4cxtDRvRVRRSgiQzNMjof904K7_xy4FU" )));
会抛出 jwt 时间相关异常:
token 被修改
单独/同时修改 header、payload 或者 signature 都会抛出 JWT 相关的异常。
JJWT 源码
TODO