jwt简介
JSON Web Token(JWT)是⼀个开放的⾏业标准(RFC 7519),它定义了⼀种简介 的、⾃包含的协议格式,⽤于 在通信双⽅传递json对象,传递的信息经过数字签名 可以被验证和信任。JWT可以使⽤HMAC算法或使⽤RSA的公 钥/私钥对来签名,防 ⽌被篡改。
最佳实践:
在使用jwt时,我们可以向jwt令牌中存放我们用户自定义的信息,但是在存放自定义信息时不建议将一些敏感信息存放进去(比如:用户密码,用户手机号,等信息,因为jwt生成的token泄露后,对方可以在jwt网站对该jwt令牌进行解密,得到里面的信息,并且别人在得到jwt令牌后也可以使用这个令牌对我们的系统进行访问,所以在我们的实践中:不会存放用户的敏感信息,然后会在里面存放客户端ip,在客户端来访问时我会检查一下,当前请求的客户端IP和jwt令牌中的ip是否一致,不一致就代表着令牌泄露,可以拒绝访问
<!--jwt工具类依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
封装的工具类
package org.xhs.utli;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Author: hu.chen
* @Description:
* @DateTime: 2022/1/26 5:18 PM
**/
public class JwtToken {
/**
* 加密字符串
*/
private String secret;
public JwtToken(String secret) {
this.secret = secret;
}
/**
* 生成令牌
*
* @param claims 存放进token中的自定义参数(比如:用户名,用户id,客户端ip等等。。。)
* @param expireTime 当前令牌的过期时间,单位秒
* @return
*/
public String generate(Map<String, Object> claims, long expireTime) {
Date nowDate = new Date();
//过期时间
Date expireDate = new Date(nowDate.getTime() + expireTime * 1000);
if (claims == null) {
claims = new HashMap<>(8);
}
return Jwts.builder()
//存放自定义值
.setClaims(claims)
//当前时间
.setIssuedAt(nowDate)
//过期时间
.setExpiration(expireDate)
//加密
.signWith(SignatureAlgorithm.HS512, secret)
.compact();
}
/**
* 获取jwt令牌失效时间(单位秒)
*/
public long getExpirationTime(String token) {
Claims claim = getClaim(token);
Date expiration = claim.getExpiration();
long time = (expiration.getTime() - System.currentTimeMillis()) / 1000;
return time;
}
/**
* 获取jwt令牌生成时间时间
*/
public Date getIssuedAtTime(String token) {
Claims claim = getClaim(token);
return claim.getIssuedAt();
}
/**
* 验证token是否失效
*
* @param token
* @return true:有效 false:无效
*/
public boolean isExpired(String token) {
try {
Claims claim = getClaim(token);
Date date = new Date();
final Date expiration = claim.getExpiration();
return date.before(expiration);
} catch (Exception exception) {
return false;
}
}
/**
* 获取token信息
*
* @param token
* @return
*/
public Map<String, Object> getTokenInfo(String token) {
Claims claim = getClaim(token);
return claim;
}
/**
* 解析Claims
*
* @param token
* @return
*/
private Claims getClaim(String token) {
Claims claims = null;
try {
claims = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody();
} catch (ExpiredJwtException e) {
claims = e.getClaims();
}
return claims;
}
}
测试:
public static void main(String[] args) throws InterruptedException, UnsupportedEncodingException {
// 创建 token 生成器
JwtToken jwtToken = new JwtToken("nsvnsdfvdh1243nskdvn");
//生成令牌
Map<String, Object> claims = new HashMap<>(8);
//设置自定义值
claims.put("002", "new Test()");
claims.put("userName", "chenhu");
claims.put("password", "123456");
String generate = jwtToken.generate(claims, 30);
//打印令牌
System.err.println(generate);
// String generate="eyJhbGciOiJIUzUxMiJ9.eyIwMDIiOiJuZXcgVGVzdCgpIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJ1c2VyTmFtZSI6ImNoZW5odSIsImV4cCI6MTY0MzE4OTk2MiwiaWF0IjoxNjQzMTg5OTMyfQ.07Yw-rsQ4MR_kHkZCg8P-fI-ANYJnemRQpnv6sHVv79furxnuqa2Y6V2wVchiESjMm2RL2u2B-s09vIBRaV8aw";
// 验证token是否有效
System.err.println(jwtToken.isExpired(generate));
// 获取token 还有多长时间失效(单位秒)
System.err.println(jwtToken.getExpirationTime(generate));
// 获取token 生成时间
System.err.println(jwtToken.getIssuedAtTime(generate));
// 获取jwt令牌中自定义信息
Map<String, Object> tokenInfo = jwtToken.getTokenInfo(generate);
System.err.println(tokenInfo.get("002"));
System.err.println(tokenInfo.get("userName"));
System.err.println(tokenInfo.get("password"));
}