GenericFilterBean的异常不会被全局异常处理程序@ControllerAdvice捕获

时间:2016-12-12 11:02:01

标签: java spring spring-security servlet-filters

我有一个org.springframework.web.filter.GenericFilterBean过滤器。我希望在用户未获得授权时抛出异常并使用@ControllerAdvice捕获此异常。但似乎处理程序不这样做。

过滤方法

@Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        ClientAuthentication auth = (ClientAuthentication) authenticationService.getAuthentication(httpRequest, httpResponse);
        SecurityContextHolder.getContext().setAuthentication(auth);

        if (auth.isAuthenticated()) {
            chain.doFilter(request, response);
        } else {
            ObjectMapper mapper = new ObjectMapper();
            response.setCharacterEncoding("UTF-8");
            httpResponse.getWriter().write(mapper.writeValueAsString(auth.getInfo()));
        }
    }

它有效,但缺点是我想捕获异常并将异常消息呈现给客户端关于Content-TypeAccept HTTP标头。此解决方案只提供我想要的内容,但只提供JSON,我的应用程序必须处理XMLJSON

异常处理程序

当我从@Controller@RestController但不从HTTP过滤器中抛出异常时,它会起作用。

    @ControllerAdvice
    class GlobalExceptionHandler {

        private static final Logger LOGGER = LogManager.getLogger(GlobalExceptionHandler.class);

        @ExceptionHandler(BadRequestException.class)
        @ResponseStatus(HttpStatus.BAD_REQUEST)
        public
        @ResponseBody
        ResponseMessage badRequestException(BadRequestException ex) {
            return ex.getResponseMessage();
        }

/** rest omitted .... **/

    }

更新#1

这是我的Spring Security配置,其中设置了AuthFilter过滤器。

@EnableWebSecurity
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Configuration
    @Order(1)
    public static class ApiSecurity extends WebSecurityConfigurerAdapter {

        private static Logger LOG = LogManager.getLogger(ApiSecurity.class);

        @Bean
        AuthenticationEntryPoint authenticationEntryPoint() {
            LOG.debug("authenticationEntryPoint bean");
            return new RestAuthenticationEntryPoint();
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http.csrf().disable();

            http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
                    .and()
                    .servletApi()
                    .and()
                    .headers().cacheControl();

            http.antMatcher(ApiController.API_ROOT + "/**").authorizeRequests().anyRequest().authenticated()
                    .and()
                    .addFilterBefore(new AuthFilter(), UsernamePasswordAuthenticationFilter.class);

        }

        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers(ApiController.API_ROOT + "/sandbox/**");
        }

    }

    @Configuration
    public static class WebFormSecurity extends WebSecurityConfigurerAdapter {

        @Autowired
        private UserDetailsService defaultUserService;

        @Autowired
        private PasswordEncoder passwordEncoder;

        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.userDetailsService(defaultUserService).passwordEncoder(passwordEncoder);
        }

        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/public/**");
        }

        @Override
        protected void configure(HttpSecurity http) throws Exception {

            http.authorizeRequests().anyRequest().fullyAuthenticated().and().formLogin()
                    .loginPage("/login").failureUrl("/login?error").permitAll().and()
                    .logout().permitAll();


        }
    }

}

0 个答案:

没有答案