文章目录
前言
最近一直封在家里没啥事儿干,也就近一年都没有更新内容了,今天就索性记一下笔记吧
一、什么是JWT
官方网址:https://jwt.io/introduction/
json web token(JWT)是一个开放标准(RFC7519),他定义了一种紧凑的、自包含的方式,用于在各方之间以JSON对象安全地址传输信息。此信息可以验证和信任,因为他是数字签名的。JWT可以使用秘密(HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。
二、JWT能做什么
1.授权
这是使用JWT的最常见的方案。一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由、服务和资源。单点登录是当前广泛使用JWT的一项功能,因为它的开销很小并且可以在不同的域中轻松使用。
2.信息交换
JSON WEB TOKEN是在各方之间安全的传输信息的好方法。因为可以对JWT进行签名(例如使用公钥/私钥对),所以您可以确保发件人的真实性(不可抵赖)。此外,由于签名是使用标头和有效负载计算的,因此您还可以验证内容是否遭到篡改。
三、为什么使用JWT
四、JWT的结构是什么
五、使用JWT
1.引入依赖
<!---jwt-->
<dependency>
<groupId>com.auth0</groupId>
<artifactId>java-jwt</artifactId>
<version>3.4.0</version>
</dependency>
2.生成token
3.根据令牌和签名解析数据
4.常见异常信息
六、封装工具类
/**
* jwt工具类
* @author ren
* @description
* @date 2022年02月14日 11:17:34
*/
public class JwtUtils {
/**
*payload主体key
*/
public static String subjectName;
/**
*密钥
*/
public static String secret;
/**
* 过期时间
*/
public static int expire;
/**
* 日期单位
*/
public static int timeUnit;
static {
Properties properties = new Properties();
try {
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream("application.properties"));
subjectName = properties.getProperty("myconfig.jwt.subjectName");
secret = properties.getProperty("myconfig.jwt.secret");
expire = Integer.valueOf(properties.getProperty("myconfig.jwt.expire"));
timeUnit = Integer.valueOf(properties.getProperty("myconfig.jwt.timeUnit"));
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 生成token
* @param payload
* @return
*/
public static String createToken (String payload){
Calendar nowDate = Calendar.getInstance();
nowDate.add(timeUnit, expire);
//过期时间
Date expireDate = nowDate.getTime();
return JWT.create().withClaim(subjectName,payload)
.withExpiresAt(expireDate).sign(Algorithm.HMAC256(secret));
}
/**
* 获取token中的payload
* @param token
* @return
*/
public static String getTokenPayload (String token) {
return JWT.require(Algorithm.HMAC256(secret)).build()
.verify(token).getClaim(subjectName).asString();
}
}
七、整合SpringBoot
经上边的讲解我们知道JWT是首次登录的时候生成的,上边我们也定义了JWT的工具类,于是我们可以在登录的业务层中生成token并返回给前端用户(这里就不展示源码了)。那调用需要验证的接口时该如何呢?我们可以定义拦截器进行校验。
1.定义JWT拦截器
/**
* JWT拦截器
* @author ren
* @description
* @date 2022年02月15日 09:43:52
*/
public class JWwtInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
AjaxResult result = null;
try {
//本系统默认前端把token放到了请求头中,key为token
String token = request.getHeader("token");
//获取JWT中的payload信息(在getTokenPayload方法中有调用校验,所以如果抛出异常就说明没有校验通过,反之就是校验通过了)
String payload = JwtUtils.getTokenPayload(token);
result = AjaxResult.success();
//可以在这里调用JwtUtils重置超时时间(我这里JwtUtils没有定义该方法就不演示了)
return true;
} catch (SignatureVerificationException e) {
e.printStackTrace();
result = AjaxResult.error("无效签名!");
}catch (TokenExpiredException e) {
e.printStackTrace();
result = AjaxResult.error("token过期!");
}catch (AlgorithmMismatchException e) {
e.printStackTrace();
result = AjaxResult.error("token算法不一致!");
}catch (Exception e) {
e.printStackTrace();
result = AjaxResult.error("token无效!");
}
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(JsonUtils.objectToJson(result));
return false;
}
}
2.注册JWT拦截器
/**
* mvc拦截器
* @author ren
* @description
* @date 2022年02月15日 09:56:00
*/
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
//jwt身份验证的拦截器
registry.addInterceptor(new JWwtInterceptor())
.addPathPatterns("/**")//添加所有路径需要验证token
.excludePathPatterns("/user/register");//排除注册的链接不需要验证token
}
}
3.获取JWT中的Payload信息
可以在BaseController或者BaseService中定义方法获取Payload信息
protected Employee getEmployeeForJwt(HttpServletRequest request){
String payload = JwtUtils.getTokenPayload(request.getHeader("token"));
return JsonUtils.jsonToPojo(payload,Employee.class);
}
八、致谢
本博客总结于B站编程不良人,JWT认证原理、流程整合springboot实战应用。