1. 引入依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.3</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.12.3</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId> <!-- or jjwt-gson if Gson is preferred -->
<version>0.12.3</version>
</dependency>
或者
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.12.3</version>
</dependency>
2. 生成JWT
指定签名算法并生成密钥(signing key)
SecretKey key = Jwts.SIG.HS256.key().build();
生成JWT,设置完各项参数后,使用.compact()
生成JWT
public static String generateToken(String username) {
Date now = new Date();
Date expiration = new Date(now.getTime() + 360000);
String jwt = Jwts.builder()
.header()
.and()
.expiration(expiration)
.signWith(key)
.subject(username)
.compact();
return jwt;
}
3. 配置JWT header
3.1. JwtBuilder.header()
JwtBuilder
的header()
方法,配置完header后,调用.and()
表明header配置完成,返回到JwtBuilder
,再去配置payload等
and
相当于结束符,表示结束当前标签
String jwt = Jwts.builder()
.header() // <----
.keyId("aKeyId")
.x509Url(aUri)
.add("someName", anyValue)
.add(mapValues)
// ... etc ...
.and() // go back to the JwtBuilder
.subject("Joe") // resume JwtBuilder calls...
// ... etc ...
.compact();
你不需要设置alg、enc或zip标头——JJWT总是会根据需要自动设置它们
JwtBuilder.header()
下的.add()
方法支持键值对
3.2. Jwts.header()
如果你想在使用JwtBuilder的上下文中创建一个独立的header,可以直接使用Jwts.header()
,最后使用.build()
生成一个Header实例
Header commonHeader = Jwts.header()
.keyId("aKeyId")
.x509Url(aUri)
.add("someName", anyValue)
.add(mapValues)
// ... etc ...
.build() // <---- not 'and()'
这种方式适用于需要提取公共header参数的JWT,该公共header可被任意JwtBuilder
使用
String jwt = Jwts.builder()
.header()
.add(commonHeader) // 将上面创建的公共header引入
.add("specificHeader", specificValue) // jwt-specific headers...
.subject("whatever")
// ... etc ...
.compact();
4. 配置JWT Payload
JWT Payload 可以是任何东西——任何可以表示为字节数组的东西,比如文本、图像、文档等等。
JwtBuilder
支持两种不同的JWT Payload选项
content
JWT Payload 是任意字节数组claims
JWT Payload 是一个JSON声明对象
注意:content和claims不能同时使用
4.1. 任意字节数组
Jwts.builder()
的.content(content, "text/plain")
方法,.content()
方法有两个参数,第一个参数是实际的字节数组,第二个参数是媒体类型的字符串标识符
常见的有
text/html
HTML格式text/plain
纯文本格式text/ xml
XML格式image/ jpeg
jpg图片格式image/png
png图片格式
byte[] content = "Hello World".getBytes(StandardCharsets.UTF_8);
String jwt = Jwts.builder()
.content(content, "text/plain") // <---
.build();
4.2. JSON声明对象
标准的(官方提供的7个字段)
issuer
: sets theiss
(Issuer) Claimsubject
: sets thesub
(Subject) Claimaudience
: sets theaud
(Audience) Claimexpiration
: sets theexp
(Expiration Time) ClaimnotBefore
: sets thenbf
(Not Before) ClaimissuedAt
: sets theiat
(Issued At) Claimid
: sets thejti
(JWT ID) Claim
String jws = Jwts.builder()
.issuer("me")
.subject("Bob")
.audience("you")
.expiration(expiration) //a java.util.Date
.notBefore(notBefore) //a java.util.Date
.issuedAt(new Date()) // for example, now
.id(UUID.randomUUID().toString()) //just an example id
自定义的
自定义单个增加字段,调用JwtBuilder
的claim
方法
String jws = Jwts.builder()
.claim("hello", "world")
.claim("teacher", "good")
自定义批量增加字段,调用JwtBuilder
的claims(Map)
方法,claims()
方法中的参数是一个map类型
String jws = Jwts.builder()
.claims(Map)
// ... etc ...
5. 为JWT签名
JWT规范确定了13个标准签名算法——3个秘密密钥算法和10个非对称密钥算法
生成密钥SecretKey
,使用Jwts.SIG
方法
SecretKey key = Jwts.SIG.HS256.key().build(); //or HS384.key() or HS512.key()
使用signWith()
签名
String jws = Jwts.builder()
.subject("Joe")
.signWith(key)
.compact();
6. 解析JWT
使用Jwts.parser()
方法创建一个 JwtParserBuilder
,可以调用.keyLocator()
,.verifyWith()
, .decryptWith()
方法去解析JWT中的信息
需要注意parser()
下调用的方法应该放在 try/catch
代码块中执行
public static String getClaimsByToken(String token) {
try{
Claims claim = Jwts.parser()
.verifyWith(key)
// or .keyLocator(keyLocator) dynamically locate signing or encryption keys
// or .decryptWith(key) a constant key used to decrypt all encrypted JWTs
.build() // 结束 parser
.parseSignedClaims(token) // or parseSignedClaims, parseEncryptedClaims, parseSignedContent, parse
.getPayload();
return claim.toString();
}catch (JwtException e){
System.out.println(e.getStackTrace());
return null;
}
}