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

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

 

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