目录
目标
- 熟悉JWT鉴权流程,能通过代码实现项目上的鉴权(这里以登录作为案例讲解,拦截器实现略。)。
JWT简介
JWT即Json Web Token的缩写,在Web应用中,将数据以Json格式进行传输,通过加密、签名等算法保证数据传输的安全性。
JWT的优点
- 共享会话:前端保存token,避免了为分布式系统做会话共享的操作;
- 跨语言:Json格式的通用性决定了这一特性;
- 减少数据访问:用户信息保存在token中,避免多次去数据库查询用户信息。
JWT的数据结构
- 头部(Base64编码):使用了哪一种签名算法和令牌。
- 有效载荷(Base64编码):可自定义内容,一般存放用户的非敏感(如:姓名、角色等)信息,而敏感信息(如:密码、手机号等)是不推荐存放的。
- 验证签名:包含:头部(Base64编码)、有效载荷(Base64编码)、密钥,然后使用我们指定的签名算法加密。
JWT登录鉴权流程
代码
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.10.3</version>
</dependency>
package com.ctx.jwt.auth;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.AlgorithmMismatchException;
import com.auth0.jwt.exceptions.SignatureVerificationException;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
public class JWTUtils {
//注意:密钥一定要复杂且保密。
private static final String SIGN = "123456";
public static void main(String[] args) {
//生成token
String jwt = JWTUtils.getJWT();
System.out.println(jwt);
//验证token
Map<String, Object> map = JWTUtils.checkToken(jwt);
System.out.println(map);
//获取token信息
Map<String, Object> tokenInfo = tokenInfo(jwt);
System.out.println(tokenInfo);
}
//生成JWT(实际项目中放在登录成功后执行,并将其返回给前端。)
public static String getJWT() {
Map<String, String> map = new HashMap<>();
map.put("loginName", "huangshang");
map.put("studentName", "黄裳");
//过期时间(我这里设置2秒后过期。方便调试看结果。)
Calendar c = Calendar.getInstance();
c.add(Calendar.SECOND, 2);
//创建一个JWT
JWTCreator.Builder builder = JWT.create();
//有效载荷部分(我这里自定义有效载荷的内容(非敏感信息)是:登录名、学生姓名。)
for (Object key : map.keySet()) {
builder.withClaim((String) key, map.get(key));
}
//token过期时间(也可以不设置过期时间,这里根据登录业务明显需要。)
builder.withExpiresAt(c.getTime());
//算法签名部分(自定义算法和密钥,注意:密钥一定要复杂且保密。)
String token = builder.sign(Algorithm.HMAC256(SIGN));
return token;
}
//验证token
public static Map<String, Object> checkToken(String token) {
Map<String, Object> map = new HashMap<>();
map.put("result", true);
//创建验证对象
JWTVerifier v = JWT.require(Algorithm.HMAC256(SIGN)).build();
try {
DecodedJWT decodedJWT = v.verify(token);
} catch (TokenExpiredException e) {
map.put("msg", "token过期");
map.put("result", false);
} catch (SignatureVerificationException e) {
map.put("msg", "无效签名");
map.put("result", false);
} catch (AlgorithmMismatchException e) {
map.put("msg", "算法不一致");
map.put("result", false);
} catch (Exception e) {
map.put("msg", "无效的token");
map.put("result", false);
}
return map;
}
//获取token信息
public static Map<String, Object> tokenInfo(String token) {
Map<String, Object> map = new HashMap<>();
map.put("result", true);
//创建验证对象
JWTVerifier v = JWT.require(Algorithm.HMAC256(SIGN)).build();
try {
DecodedJWT decodedJWT = v.verify(token);
String loginName = decodedJWT.getClaim("loginName").asString();
String studentName = decodedJWT.getClaim("studentName").asString();
String date = stampToDate(decodedJWT.getExpiresAt());
map.put("loginName", loginName);
map.put("studentName", studentName);
map.put("date", date);
} catch (TokenExpiredException e) {
map.put("msg", "token过期");
map.put("result", false);
} catch (SignatureVerificationException e) {
map.put("msg", "无效签名");
map.put("result", false);
} catch (AlgorithmMismatchException e) {
map.put("msg", "算法不一致");
map.put("result", false);
} catch (Exception e) {
map.put("msg", "无效的token");
map.put("result", false);
}
return map;
}
public static String stampToDate(Date date) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = simpleDateFormat.format(date);
return dateString;
}
}
官网解析Token
点击进入JWT官网;