環境: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
控制檯: ------忽略此接口------