提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
- 前言
- 一、JWT是什么?
- 二、为什么选择JWT
- 1.支持跨域访问
- 2.无状态
- 3.更适用于移动端
- 三、JWT使用
- 1.工具类
- 2.使用
- 总结
前言
本文介绍了JWT的基本概念,优点和使用方法,并提供了简单的jwtToken的工具类以便快速上手使用
提示:以下是本篇文章正文内容,下面案例可供参考
一、JWT是什么?
JWT是英文JSON Web Token的缩写,看到token我们的第一印象他是认证用的。
通俗地说,JWT的本质就是一个不规则字符串,它可以将用户相关信息保存到一个Json字符串中,然后进行编码后得到一个JWT token,并且这个JWT token带有签名信息,接收后可以校验是否被篡改。
二、为什么选择JWT
1.支持跨域访问
cookie是无法跨域的,而token由于没有用到cookie(前提是将token放到请求头中),所以跨域后不会存在信息丢失问题
2.无状态
token机制在服务端不需要存储session信息,因为token自身包含了所有登录用户的信息,所以可以减轻服务端压力
3.更适用于移动端
当客户端是非浏览器平台时,cookie是不被支持的,此时采用token认证方式会简单很多
三、JWT使用
1.工具类
代码如下:
/**
* <p>jwt token工具类</p>
* <pre>
* jwt的claim里一般包含以下几种数据:
* 1. iss -- token的发行者
* 2. sub -- 该JWT所面向的用户
* 3. aud -- 接收该JWT的一方
* 4. exp -- token的失效时间
* 5. nbf -- 在此时间段之前,不会被处理
* 6. iat -- jwt发布时间
* 7. jti -- jwt唯一标识,防止重复使用
* </pre>
*/
public class JwtTokenUtil {
/**
* 获取用户名从token中
*/
public static String getUsernameFromToken(String token) {
return getClaimFromToken(token).getSubject();
}
/**
* 获取jwt发布时间
*/
public static Date getIssuedAtDateFromToken(String token) {
return getClaimFromToken(token).getIssuedAt();
}
/**
* 获取jwt失效时间
*/
public static Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token).getExpiration();
}
/**
* 获取jwt接收者
*/
public static String getAudienceFromToken(String token) {
return getClaimFromToken(token).getAudience();
}
/**
* 获取私有的jwt claim
*/
public static String getPrivateClaimFromToken(String token, String key) {
return getClaimFromToken(token).get(key).toString();
}
/**
* 获取jwt的payload部分
*/
public static Claims getClaimFromToken(String token) {
return Jwts.parser()
.setSigningKey(JwtConstants.SECRET)
.parseClaimsJws(token)
.getBody();
}
/**
* 解析token是否正确,不正确会报异常<br>
*/
public static void parseToken(String token) throws JwtException {
Jwts.parser().setSigningKey(JwtConstants.SECRET).parseClaimsJws(token).getBody();
}
/**
* <pre>
* 验证token是否失效
* true:过期 false:没过期
* </pre>
*/
public static Boolean isTokenExpired(String token) {
try {
Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
} catch (ExpiredJwtException expiredJwtException) {
return true;
}
}
/**
* 生成token(通过用户名和签名时候用的随机数)
*/
public static String generateToken(String userId) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userId);
}
/**
* 生成token(通过用户名和签名时候用的随机数) 可存额外字段 claims
*/
public static String generateToken(Map<String, Object> claims, String userId) {
return doGenerateToken(claims, userId);
}
/**
* 生成token
*/
private static String doGenerateToken(Map<String, Object> claims, String subject) {
Date createdDate = new Date();
Date expirationDate = new Date(createdDate.getTime() + JwtConstants.EXPIRATION * 1000);
return Jwts.builder()
.setClaims(claims)
.setSubject(subject)
.setIssuedAt(createdDate)
.setExpiration(expirationDate)
.signWith(SignatureAlgorithm.HS512, JwtConstants.SECRET)
.compact();
}
/**
* 获取混淆MD5签名用的随机字符串
*/
public static String getRandomKey() {
return getRandomString(6);
}
/**
* 获取随机字符,自定义长度
*
* @author soofuju
* @Date 2018/3/18 21:55
*/
public static String getRandomString(int length) {
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
}
2.使用
代码如下:
public static void main(String[] args) {
Map<String, Object> claims = new HashMap<>();
claims.put("info", new UserTerminalAuthDO().setNickName("张三").setMobile("13811111111"));
//生成JWTtoken
String token = JwtTokenUtil.generateToken(claims, "1");
//获取token存储的userId
String usernameFromToken = JwtTokenUtil.getUsernameFromToken(token);
//获取token存储的claims
Claims claimFromToken = JwtTokenUtil.getClaimFromToken(token);
}
总结
JWT的确有他自己的优势,但是任何的方法都存在它的局限性,JWT也不例外:Jwt生成之后无法修改(发生变化)、而且JWT的token长度与其包含用户信息多少正相关,传输开销较大、无法吊销令牌,只能等待令牌自身过期。所以还是需要根据具体的开发需求选择适合的方法进行开发。