我有一个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-Type
和Accept
HTTP标头。此解决方案只提供我想要的内容,但只提供JSON,我的应用程序必须处理XML
和JSON
。
异常处理程序
当我从@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();
}
}
}