springboot自定義權限攔截器的簡單實現

環境: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

控制檯:         ------忽略此接口------

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章