一、JWT简单介绍
JWT(JSON Web Token)是一种基于JSON的加密令牌,可以用作于前端向后端发起请求时的身份凭证。
JWT由三部分组成:
(1)header :头部。指明了JWT使用的签名算法(例如HS256)和令牌类型(JWT),经过base64编码后形成令牌第一部分。
(2) payload :负载。简单来说该部分是可以放入一些不敏感的数据后经过base64编码得到,例如登录用户的id:
{
"id" : 1
}
(3) signature : 签名。该部分保证了JWT令牌的安全性。这里我们需要自定义一个密钥(简单来说就是一个自定义的字符串)。由header和payload经过base64编码后加上自定义密钥使用上文指定的HS256算法进行加密形成令牌的第三部分
所以最终生成的JWT令牌就会长这个样子 : header.payload.signature, 例如:
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjh9.0m8EK5x87XIDaEH7Yl7CbQi1Zj48-QoGIronj5YVCaM
这里就主要分享一下日常写springboot项目时如何去利用JWT完成简单的一个登录身份校验功能
二、依赖
使用JWT首先要引入其依赖,因为我们使用的是hutool工具包中的JWT功能,所以这里我们引入的是hutool工具包的依赖
<!--hutool-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.17</version>
</dependency>
三、使用
(1)创建JWT
要完成登录校验,我们首先要根据前端传来的登录参数查询我们的数据库看此次登录的用户是否存在,若存在我们就可以使用hutool包中的JWTUtil类的createToken() 创建JWT。
HashMap<String, Object> map = new HashMap<>();
map.put("userId", user.getId());
String key = "wxxcxlogin";
String token = JWTUtil.createToken(map, key.getBytes());
System.out.println(token);
createToken()方法有很多重载,这里我们选择使用的方法需要两个参数,
- 一个是用户自定的信息(payload)我们使用HashMap来传递,保存的是从数据库中查到的此次登录的用户ID。
- 另一个是上文提到的自定义的密钥。(ps:这里只是简单使用一下,一般来说应该把密钥定义在配置文件中)
执行完方法后会自动生成一个token。
(2)使用JWT
创建完后我们就要把JWT传递给前端,前端会将后端传递的JWT进行保存,并在之后需要登录身份验证的请求中都会在请求头中加上保存的JWT(也可封装一个共同的请求),以便后端能够从请求头中获取到JWT并加以校验,这里前端我们使用微信小程序作为示例:
wx.setStorageSync('token', res.data.data.token)
header: {
'Content-Type': 'application/json',
'token': wx.getStorageSync('token'),
...header,
},
这里只是简单示例一下,具体前端的逻辑还要小伙伴们根据自己的项目情况完成更改。
(3)后端校验JWT
前端请求发出后,在后端中我们需要去创建一个拦截器来拦截请求并获取请求头中的JWT完成校验。
具体代码逻辑如下:
@Component
@Slf4j
public class UserLoginInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1. 获取前端传来的token
String token = request.getHeader("token");
log.info("已获取到token:{}",token);
// 2.判空
if( token == null || token.equals("")){
log.info("未登录,拒绝访问");
return false;
}
// 3.验证并解析token , 获取数据
String key = "wxxcxlogin";
boolean result = JWTUtil.verify(token, key.getBytes());
if( !result ){
log.info("token错误,拒绝访问");
return false;
}
JWT jwt = JWTUtil.parseToken(token);
Integer userId = (Integer) jwt.getPayload("userId");
// 4.判断
if( userId == null || userId <= 0) {
log.info("token错误,拒绝访问");
return false;
}
// 5.token正确,保存用户id并放行
Context.setCurrentId(userId);
log.info("token校验成功,成功登录");
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
// 清除掉ThreadLocal中的id
Context.removeCurrentId();
}
}
这里使用ThreadLocal完成保存用户id的操作,这样方便后续使用
具体代码逻辑如下:
public class Context {
private static ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
public static Integer getCurrentId(){
return threadLocal.get();
}
public static void setCurrentId(Integer id) {
threadLocal.set(id);
}
public static void removeCurrentId() {
threadLocal.remove();
}
}
写完拦截器我们需要去配置类中注册拦截器
具体代码逻辑如下:
@Configuration
public class MvcConfig extends WebMvcConfigurationSupport {
@Autowired
UserLoginInterceptor userLoginInterceptor;
@Override
protected void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(userLoginInterceptor)
.addPathPatterns("/**")
.excludePathPatterns("/user/**")
}
}
在配置类中我们可以用addPathPatterns和excludePathPatterns等方法来控制这个拦截器需要拦截和放行哪些请求。
(4)测试
1.首先正常登录获取一个token;
2.其次可以用postman发起一个需要被拦截的请求并在其请求头中加入正确的token,看请求是否可以正常通过;
3.然后修改token值并发起一个同样的请求,看请求是否被拦截。
结语:这样就使用hutool工具包完成了一个简易的基于JWT的登录身份校验功能