能成功解析出结果的前提是两次的盐是一样的才行
Claims map = Jwts.parser().setSigningKey("changwu") .parseClaimsJws("eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI2NjYiLCJzdWIiOiLlvKDkuIkiLCJleHAiOjE1NjU2MTg1MjUsImlhdCI6MTU2NTYxODQ2NSwicm9sZSI6ImFkbWluIn0.GDVfLq-ehSnMCRoxVcziXkirjOg34SUUPBK5vAEHu80") .getBody(); System.out.println("用户id" + map.getId()); System.out.println("用户名" + map.getSubject()); System.out.println("token过期时间" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(map.getExpiration())); System.out.println("用户登录时间" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(map.getIssuedAt())); System.out.println("用户的角色是:"+map.get("role")); 拦截器注意哦,使用的是SpringMvc的拦截器,而不是Servlet的过滤器
拦截器的体系架构在拦截器的体系中,我们常用的是上面的来两个
HandlerInterceptor: 是顶级接口如下:
虽然是接口, 但是拥有jdk8的特性,是默认的方法,所以允许我们挑选它的部分方法实现而不会报错
prehandler: 请求到达控制器之间被回调,可以在这里进行设置编码,安全控制,权限校验, 一般全部返回ture,表示放行
postHandler: 控制器处理请求之后生成了ModelAndView,但是未进行渲染,提供了修改ModelAndView的机会
afterCompletion: 返回给用户ModelAndView之后执行, 用于收尾工作
第二个是HandlerInterceptorAdapter如下图
这个适配器方法全是空实现,同样可以满足我们的需求,但是它同时实现了AsyncHandlerInterceptor,拥有了一个新的方法,afterConcrruentHandingStarted(request,response,handler)
这个方法会在Controller方法异步执行时开始执行, 而Interceptor的postHandle方法则是需要等到Controller的异步执行完才能执行
编码实现其实到这里改如何做已经清晰明了
用户登录,授权授权的很简单
用户发送登录请求提交form表单
后端根据用户名密码查询用户的信息
把用户的信息封装进jwt的载荷部分
返回给前端token
用户再次请求,鉴权后台会有很多方法需要指定权限的人才能访问, 所谓鉴定权限,其实就是把前端放在请求头中的token信息解析出来,如果解析成功了,说明用户的合法的,否则就提示前端用户没有权限
把token从请求头中解析出来的过程,其实是在大量的重复性工作,所以我们放在拦截器中实现
使用拦截器两步走
第一步,继承HandlerInterAdapter,选择重写它的方法
设计的逻辑,这个方法肯定要返回true, 因为后台的方法中肯定存在大量的不需要任何权限就能访问的方法
所以这个方法的作用就是,解析出请求头中的用户的权限信息,重新放回到request中,
这样每个需要进行权限验证的请求,就不需要再进行解析请求头,而是直接使用当前回调方法的处理结果
@Component public class RequestInterceptor extends HandlerInterceptorAdapter { @Autowired JwtUtil jwtUtil; // 在请求进入处理器之前回调这个方法 @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 获取请求头 String header = request.getHeader("Authorization"); // 请求头不为空进行解析 if (StringUtils.isNotBlank(header)) { // 按照我们和前端约定的格式进行处理 if (header.startsWith("Bearer ")){ // 得到令牌 String token = header.substring(7); // 验证令牌 try{ // 令牌的解析这里一定的try起来,因为它解析错误的令牌时,会报错 // 当然你也可以在自定义的jwtUtil中把异常 try起来,这里就不用写了 Claims claims = jwtUtil.parseJWT(token); String roles =(String) claims.get("roles"); System.err.println("roles=="+roles); if (roles!=null&&"admin".equals(roles)){ request.setAttribute("role_admin",token); } if (roles!=null&&"user".equals(roles)){ request.setAttribute("role_user",token); } }catch (Exception e){ throw new RuntimeException("令牌不存在"); } } } return true; } }