微服务安全与权限-JWT[02整合微服务]

203 阅读1分钟

这是我参与8月更文挑战的第12天,活动详情查看:8月更文挑战

JWT整合spingboot+redis

controller

将生成token写入登录的controller中并且存入redis

@ResponseBody
   @PostMapping("/login")
   /*认证生成token*/
   public HashMap< String, Object > login(String username,String password){
       HashMap< String, String > map = new HashMap<>();
       HashMap< String, Object > map1 = new HashMap<>();
       try {
           User user = loginSercice.loginSuccess(username, password);
           if (user != null) {
               //将用户名和密码存放map,用于生成搭载信息的token,注意,不要放密码进去!
               map.put("id", user.getId());
               map.put("username", user.getUsername());
               String token = JWTUtil.create(map);
               map1.put("status",200);
               map1.put("token",token);
               return map1;
          }
      }catch (Exception e){
               map1.put("status",500);
      }
       return map1;
  }

拦截器

验证token写进handler拦截器中,除了登录功能,其他功能都会被拦截检查token

token 存放在request的请求头中,所以可以通过request.getHeader("token")来获取token

​
   /*这部分相当于验证token的功能*/
   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
​
       HashMap< String, Object > map = new HashMap<>();
​
       //获得token
       String token = request.getHeader("token");
       try{
           JWTUtil.verify(token);  //验证令牌
           //当数据库中的token没有过期且与前端传来的token相同
           if(StringUtils.equals(redisUtil.get("token"),token)){
               map.put("message","不拦截");
               return true;
          }else {
               map.put("error","登录超时,请重新登录");
          }
      }catch (Exception e){
           e.printStackTrace();
           map.put("message","没有登录,请重新登录");
      }
       map.put("status",false);
       //将map转换为json
       String json = new ObjectMapper().writeValueAsString(map);
       //设置response的格式为json   比那与前后端
       response.setContentType("application/json;charset=UTF-8");
       response.getWriter().println(json);
           return false;
  }
}
​

拦截器部署

别忘了将拦截器应用到webMVC中

并将除了登录生成token的其他所有的访问路径纳入拦截器的范围

那么每次访问请求路径都会经过拦截器来校验。

当登录后,在拦截器中读取redis的值与token进行对比时,出现redis读取的值为null

查找得知,拦截器在springcontext之前就加载了,即实例化在@Bean之前执行,那么当拦截器运行,redisTemplate实际上是注入失败的(无法进行读取操作)

所以我们要先实例化拦截器,再将拦截器配置进去

@Bean
   public JWTHandler getHandler(){
       return new JWTHandler();
  }
   
   @Override
   public void addInterceptors(InterceptorRegistry registry) {
       
       //调用实例化的方法
       registry.addInterceptor(getHandler())
              .addPathPatterns("/login/**")
              .excludePathPatterns("/login/login");
  }