自定义过滤器
@Slf4j @Component public class JwtAuthorizationTokenFilter extends OncePerRequestFilter { private final UserDetailsService userDetailsService; private final JwtTokenUtil jwtTokenUtil; private final String tokenHeader; public JwtAuthorizationTokenFilter(@Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, @Value("${jwt.header}") String tokenHeader) { this.userDetailsService = userDetailsService; this.jwtTokenUtil = jwtTokenUtil; this.tokenHeader = tokenHeader; } @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { final String requestHeader = request.getHeader(this.tokenHeader); String username = null; String authToken = null; if (requestHeader != null && requestHeader.startsWith("Bearer ")) { authToken = requestHeader.substring(7); try { username = jwtTokenUtil.getUsernameFromToken(authToken); } catch (ExpiredJwtException e) { log.error(e.getMessage()); } } if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { // It is not compelling necessary to load the use details from the database. You could also store the information // in the token and read it from it. It's up to you ;) JwtUser userDetails = (JwtUser)this.userDetailsService.loadUserByUsername(username); // For simple validation it is completely sufficient to just check the token integrity. You don't have to call // the database compellingly. Again it's up to you ;) if (jwtTokenUtil.validateToken(authToken, userDetails)) { UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); SecurityContextHolder.getContext().setAuthentication(authentication); } } chain.doFilter(request, response); } }1.自定义拦截器
@Component public class JwtInterceptor extends HandlerInterceptorAdapter { /** * 简化获取token数据的代码编写(判断是否登录) * 1.通过request获取请求token信息 * 2.从token中解析获取claims * 3.将claims绑定到request域中 */ @Autowired private JwtUtils jwtUtils; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 1.通过request获取请求token信息 String authorization = request.getHeader("Authorization"); //判断请求头信息是否为空,或者是否已Bearer开头 if(!StringUtils.isEmpty(authorization) && authorization.startsWith("Bearer")) { //获取token数据 String token = authorization.replace("Bearer ",""); //解析token获取claims Claims claims = jwtUtils.parseJwt(token); if(claims != null) { //通过claims获取到当前用户的可访问API权限字符串 String apis = (String) claims.get("apis"); //api-user-delete,api-user-update //通过handler HandlerMethod h = (HandlerMethod) handler; //获取接口上的reqeustmapping注解 RequestMapping annotation = h.getMethodAnnotation(RequestMapping.class); //获取当前请求接口中的name属性 String name = annotation.name(); //判断当前用户是否具有响应的请求权限 if(apis.contains(name)) { request.setAttribute("user_claims",claims); return true; }else { throw new CommonException(ResultCode.UNAUTHORISE); } } } throw new CommonException(ResultCode.UNAUTHENTICATED); } }2.配置拦截器类
@Configuration public class SystemConfig extends WebMvcConfigurationSupport { @Autowired private JwtInterceptor jwtInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(jwtInterceptor). addPathPatterns("/**"). excludePathPatterns("/frame/login","/frame/register/**"); //设置不拦截的请求地址 } }3.如果出现 no session问题,在启动类中添加一个方法
//1.配置springboot的包扫描 @SpringBootApplication(scanBasePackages = "com.ihrm") //2.配置jpa注解的扫描 @EntityScan(value="com.ihrm.domain.system") public class SystemApplication { /** * 启动方法 */ public static void main(String[] args) { SpringApplication.run(SystemApplication.class,args); } @Bean public IdWorker idWorker() { return new IdWorker(); } @Bean public JwtUtils jwtUtils() { return new JwtUtils(); } //解决no session @Bean public OpenEntityManagerInViewFilter openEntityManagerInViewFilter() { return new OpenEntityManagerInViewFilter(); } }