在我的Spring Boot应用程序中,我有以下web安全配置:
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.headers().frameOptions().disable()
.and()
.antMatcher("/**").authorizeRequests()
.antMatchers("/actuator/health").permitAll()
.antMatchers("/actuator/**").hasAuthority(Authority.Type.ROLE_ADMIN.getName())
.antMatchers("/login/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.failureUrl("/login?error").permitAll()
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout")
.and()
.csrf().csrfTokenRepository(csrfTokenRepository()).ignoringAntMatchers("/login/**")
.and()
.addFilterBefore(corsFilter, ChannelProcessingFilter.class)
.addFilterAfter(new CsrfTokenResponseHeaderBindingFilter(), CsrfFilter.class)
.addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class)
.exceptionHandling().authenticationEntryPoint(new Http403ForbiddenEntryPoint());
// @formatter:on
}
....
}
和ControllerAdvice
:
@ControllerAdvice
public class GlobalControllerExceptionHandler {
private static final String ERROR = "error";
@ExceptionHandler(value = Exception.class)
@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public Map<String, ErrorResponse> handleException(Exception exception) {
return createResponseError(exception);
}
private Map<String, ErrorResponse> createResponseError(Exception exception) {
final Map<String, ErrorResponse> responseError = new HashMap<String, ErrorResponse>();
responseError.put(ERROR, new ErrorResponse(exception.getMessage()));
return responseError;
}
}
现在,当我试图通过匿名用户访问我的安全API URL时,我收到了以下错误:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Fri May 06 22:59:05 EEST 2016
There was an unexpected error (type=Forbidden, status=403).
Access Denied
我需要在ControllerAdvice
中处理此类错误(以便返回JSON错误响应),而不是这个页面,它对所有其他异常都很好,但只对经过身份验证的用户有效。
如何通过我的GlobalControllerExceptionHandler
处理此身份验证/授权错误?
ControllerAdvice
s用于辅助Controller
类,ExceptionHandler
s用于处理Controller
s抛出的异常。AuthenticationException
和AccessDeniedException
s通常由Spring Security的AbstractSecurityInterceptor
抛出。因此,我猜您将无法使用ControllerAdvice
s捕获这些AuthenticationException
s,因为ExceptionTranslationFilter
已经捕获了它们并将它们转换为适当的HTTP响应。
更好的方法是在WebSecurityConfigurerAdapter
中使用exceptionHandling
。使用它,您可以配置AuthenticationEntryPoint
和AccessDeniedHandler
。在这里,对于拒绝访问的情况,我返回403 Forbidden
,对于丢失身份验证令牌的情况,返回401 Unauthorized
:
@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.exceptionHandling()
.accessDeniedHandler((request, response, accessDeniedException) -> {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
})
.authenticationEntryPoint((request, response, authException) -> {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
});
}
}
使用exceptionHandling
,您可以将ExceptionTranslationFilter
配置为使用accessDeniedHandler
处理AccessDeniedException
s,将authenticationEntryPoint
配置为AuthenticationException
s。查看ExceptionTranslationFilter
以了解有关该过程的更多信息。
如果你不喜欢:
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Fri May 06 22:59:05 EEST 2016
There was an unexpected error (type=Forbidden, status=403).
Access Denied
如果要自定义它,您应该提供ErrorController
的实现,并为错误返回Map<String, ErrorResponse>
。