自定义全局统一异常替换过滤器Filter中异常

1.问题

使用SpringSecurity时候,自定义过滤器不走全局统一异常,走过滤器链异常处理

2. 全局统一异常

@RestControllerAdvice
@Slf4j
public class MyExceptionHandler {

    @ExceptionHandler(CustomException.class)
    public R commonException(CustomException e) {
        log.debug("自定义异常信息:", e);
        return R.error(e.getCode(), e.getMsg());
    }

    @ExceptionHandler(Exception.class)
    public R handlerException(Exception e) {
        log.error("系统异常信息:", e);
        return R.error(StatusCode.FAIL);
    }
}

3.自定义Filter

@WebFilter(urlPatterns = "/index/getSmsCode")
public class MyFilter implements Filter {

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        ...
        throw new CustomException()
        ...
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

要使上面@WebFilter生效,需要启动类添加@ServletComponentScan("路径"),
注意,若在上面过滤器中添加@component,则urlPatterns不生效,其他url也会走此过滤器

4.解决

全局统一异常处理只能处理控制器中发生的异常。要在Spring Security过滤器链中重用此功能,需要定义过滤器并将其挂钩到安全配置中。过滤器需要将异常重定向到统一异常处理中。

①.针对自定义,特定过滤器异常走全局异常

@WebFilter(urlPatterns = "/index/getSmsCode")
@Slf4j
public class SmsFilter implements Filter {

    @Autowired
    @Qualifier("handlerExceptionResolver")
    private HandlerExceptionResolver resolver;

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        try {
            ...   
            throw new CustomException(StatusCode.ERROR_PARAMETER);
            ...
            filterChain.doFilter(servletRequest, servletResponse);
        } catch (Exception e) {
            resolver.resolveException((HttpServletRequest)request, (HttpServletResponse) servletResponse, null, e);
        }
    }
}

②.配置一处,是其他过滤器走全局也生效

自定义过滤器

@Component
public class FilterChainExceptionHandler extends OncePerRequestFilter {

    @Autowired
    @Qualifier("handlerExceptionResolver")
    private HandlerExceptionResolver resolver;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        try {
            filterChain.doFilter(request, response);
        } catch (Exception e) {
            log.error("Spring Security Filter Chain Exception:", e);
            resolver.resolveException(request, response, null, e);
        }
    }
}

然后,将创建的过滤器添加到SecurityConfiguration。您需要非常早地将其挂接到链中,因为不会捕获次过滤器之前过滤的异常。比如在LogoutFilter之前过滤,退出异常走全局

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    private FilterChainExceptionHandler filterChainExceptionHandler;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .addFilterBefore(filterChainExceptionHandler, LogoutFilter.class)
            (...)
    }

}

参考: https://stackoverflow.com/questions/34595605/how-to-manage-exceptions-thrown-in-filters-in-spring

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 夜莺2517阅读 127,752评论 1 9
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,587评论 28 53
  • 兔子虽然是枚小硕 但学校的硕士四人寝不够 就被分到了博士楼里 两人一间 在学校的最西边 靠山 兔子的室友身体不好 ...
    待业的兔子阅读 2,633评论 2 9
  • 信任包括信任自己和信任他人 很多时候,很多事情,失败、遗憾、错过,源于不自信,不信任他人 觉得自己做不成,别人做不...
    吴氵晃阅读 6,220评论 4 8