环境:IDEA,jdk1.8,springboot2.1.3,maven
一、拦截器实现类
/**
* 自定义权限拦截器
*
* @author YoonaLt
* @date 2019/10/29
*/
@Slf4j
public class CustomIntercept implements HandlerInterceptor {
/**
* 使用自定义请求头 token 验证登录权限
* <p>预处理--此方法在处理请求之前调用(controller方法调用之前)</p>
*
* @param request 请求头信息
* @param response 响应信息
* @param handler
* @return 布尔值
* @throws Exception 异常
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String reqMethod = request.getMethod();
String overlook = "OPTIONS";
// 请求方式为OPTIONS请求时,验证忽略,响应添加自定义验证请求头token.此处解决跨域问题
if (overlook.equals(reqMethod)) {
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Methods",
"POST, GET, DELETE, PUT, OPTIONS");
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Headers",
"Content-Type, x-requested-with, X-Custom-Header, token");
return true;
}
// 获取验证token
String token = request.getHeader("token");
if (StringUtils.isBlank(token)) {
log.debug("请求地址: " + request.getRequestURI() + "\n该请求未携带验证token,请核对请求");
response.setCharacterEncoding("utf-8");
response.setContentType("text/json;charset=utf-8");
ServletOutputStream servletOutputStream = response.getOutputStream();
// 不推荐直接手写json字符串,可以使用类似 fastjson 等来进行处理.
String s = "\"{\"code\":\"40000\",\"msg\":\"未携带token\"}\"";
servletOutputStream.write(s.getBytes());
servletOutputStream.flush();
servletOutputStream.close();
return false;
}
return true;
}
/**
* <p>返回处理--此方法在处理请求之后,视图渲染之前调用</p>
*
* @param request 请求
* @param response 响应
* @param handler
* @param modelAndView 模型视图
* @throws Exception 方法可能抛出的异常
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
// TODO
}
/**
* <p>结束处理--此方法在请求结束后调用</p>
*
* @param request 请求
* @param response 响应
* @param handler
* @param ex 接收到的异常
* @throws Exception 方法可能抛出的异常
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
// TODO
}
}
二、拦截器配置类
实现拦截器配置类的方式有多种:
1. 通过继承 WebMvcConfigurerAdapter 类实现。但是此类在 SpringBoot2.0 被标记过期,不推荐使用。
2. 通过继承 WebMvcConfigurationSupport 类实现。但SpringMvc已有默认配置类 WebMvcAutoConfiguration,此类被@ConditionalOnMissingBean(WebMvcConfigurationSupport.class) 注解。这个注解的意义是当没有配置WebMvcConfigurationSupport 时,此类才生效。当继承 WebMvcConfigurationSupport 类时,因为默认配置无效,所以根据需求,必需重写某些方法。比如若不重写下面方法,会导致静态资源无法访问。
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**")
.addResourceLocations("classpath:/static/")
.addResourceLocations("classpath:/templates/");
}
3. 实现 WebMvcConfigurer 接口。
此示例使用的就是这种方式。
/**
* @author YoonaLt
* @date 2019/10/30
* 拦截器配置类
*/
@Configuration
public class InterceptConfig implements WebMvcConfigurer {
/**
* 需要拦截器进行拦截的请求路径
*/
private static final List<String> ADD_PATH = Arrays.asList("/login", "/intercept/inside");
/**
* 需要拦截器忽略的请求路径
*/
private static final List<String> EXCLUDE_PATH = Arrays.asList("/intercept/out", "others");
/**
* 将拦截器注册到Ioc
*
* @return 拦截器实例
*/
@Bean
public CustomIntercept getCustomIntercept() {
return new CustomIntercept();
}
/**
* 配置拦截器过滤路径规则
*
* @param registry 拦截过滤器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(getCustomIntercept()).addPathPatterns(ADD_PATH).excludePathPatterns(EXCLUDE_PATH);
}
}
三、测试
@Slf4j
@RestController
@RequestMapping(value = "intercept")
public class InterceptController {
/**
* 拦截接口
*
* @return OK
*/
@GetMapping(value = "inside")
public String interceptInside() {
log.debug("------被拦截接口------");
return "OK";
}
/**
* 拦截忽略接口
*
* @return OK
*/
@GetMapping(value = "out")
public String interceptOut() {
log.debug("------忽略此接口------");
return "OK";
}
}
1. 访问路径 /intercept/inside 且请求头 不携带 token 时:
Response: "{"code":"40000","msg":"未携带token"}"
控制台: 请求地址: /intercept/inside
该请求未携带验证token,请核对请求
2. 访问路径 /intercept/inside 并且 携带 token 时:
Response: OK
控制台: ------被拦截接口------
3. 访问路径 /intercept/out,无论 是否携带 token :
Response: OK
控制台: ------忽略此接口------