簡體   English   中英

Spring ControllerAdvice和身份驗證/授權異常處理

[英]Spring ControllerAdvice and authentication/authorization exception handling

在我的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處理此Authentication / Authorization錯誤?

ControllerAdvice旨在幫助Controller類,而ExceptionHandler則用於處理Controller拋出的異常。 AuthenticationExceptionAccessDeniedException通常由Spring Security的AbstractSecurityInterceptor拋出。 因此,我猜測您將無法使用ControllerAdvice捕獲那些AuthenticationException ,因為ExceptionTranslationFilter已經捕獲了它們並將它們轉換為適當的HTTP響應。

更好的方法是在WebSecurityConfigurerAdapter使用exceptionHandling 使用它,您可以配置AuthenticationEntryPointAccessDeniedHandler 在這里,我將為拒絕訪問的情況返回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並使用authenticationEntryPointAuthenticationException 窺視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>以獲取錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM