需求
当你有需求要对项目的所有或部分请求做一些校验或对请求中的参数做一些处理,这时就需要用到拦截器了。
实现方式
1.编写拦截器要实现的功能。
2.配置拦截器到springboot环境。
编写拦截器
类似SpringMVC,编写拦截器并实现HandlerInterceptor接口,实现接口中需要的方法。(preHandler、postHandler、afterCompletion这里不多讲解)这里要注意拦截器所在包要在spring的扫描范围内。
@Component
public class LoginInterceptor implements HandlerInterceptor {
@Resource
JWTManager jwtManager;// jwt管理类
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
if(request.getMethod().equals("OPTIONS")) {
return false;
}
String jwt = request.getHeader("Authorization");
if(jwt==null||jwt.length()<20){
String cookie=request.getHeader("cookie");
Cookie[] cookies = request.getCookies();
for (Cookie c : cookies) {
switch(c.getName()){
case "Authorization":
jwt = c.getValue();
break;
default:
break;
}
}
}
if(jwt!=null&&!jwt.equals("")&&!jwt.equals("null")&&!jwt.equals("undefined")) {
//判断有效期
try {
jwtManager.checkAccessJWT(jwt);
return true;
} catch (SignatureException e) {
response.setStatus(401);
return false;
} catch (ExpiredJwtException e) {
response.setStatus(401);
return false;
} catch (Exception e) {
response.setStatus(401);
return false;
}
}
response.setStatus(401);
return false;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
配置拦截器到springboot环境
网上大部分的文章,都是选择继承WebMvcConfigurerAdapter,但是springboot
2.0.4.RELEASE
版本后,WebMvcConfigurerAdapter已过时(虽然还能用)。这里涉及到设计模式的思想,因为WebMvcConfigurerAdapter采用了适配器模式,所以我们可以直接去使用适配器所实现的接口即可,直接实现WebMvcConfigurer就行了。
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
public InterceptorConfig(){
super();
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//拦截规则:除了静态资源和登录接口,其他都拦截判断
registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login/**","/static/**","/error","/**/riskListForPage","/**/riskInfo");
}
@Bean
public LoginInterceptor loginInterceptor() {
return new LoginInterceptor();
}
}
这里踩了很多坑,写给大家。
1.addPathPatterns()配置拦截路径时,如果想拦截所有请求,并且你的项目的请求是多级的话(如/login/logout),拦截规则必需写成("/**")而不能是("/*"),后者只会拦截一级路径。
2.excludePathPatterns()中配置拦截中的放过拦截的白名单,这里需要加上("/error"),否则当你白名单中有个路径写错时,系统产生404错误。比如你配置了excludePathPatterns("/login"),然后你的项目中实际不存在,当你访问http://xxxx/login时,springboot会自动把请求转向/error这个路径,就还会进入拦截器,看起来就像白名单配置不生效一样。
3.这里还需要说一下excludePathPatterns()中表达式的匹配规则,我的项目中有请求是/***/***/riskListForPage、/***/***/riskList这样的三级路径,最初我在excludePathPatterns()中写的是("/riskListForPage","/riskList"),然后发现请求还是会被拦截,最后发现写成("/**/riskListForPage","/**/riskList")就可以请求跨过拦截器了。(这里后面还需要看下源码求证下)