Spring Security

时间:2016-04-30 23:11:36

标签: spring-mvc spring-security spring-boot

我有一个具有Spring Security的弹簧启动1.3.0.BUILD-SNAPSHOT应用程序。我有一个@ControllerAdvice类用于处理来自我的端点的异常,并且运行良好。但是,我无法跟踪Spring Security中的异常,例如AuthenticationException。我使用它来捕获这些异常并记录特定的消息:

@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception.getLocalizedMessage());
        throw new SessionAuthenticationException(exception.getLocalizedMessage());
    }
}

即使我有这个例外也从未被捕获:

@ControllerAdvice
public class BaseController {
    @ExceptionHandler({SessionAuthenticationException.class})
    @ResponseBody
    public ResponseEntity getSessionAuthenticationExceptionResponse(Exception exception) {

        LOGGER.error("exception.getMessage()", exception);
        return  ResponseEntity.status( HttpStatus.UNAUTHORIZED )
                        .contentType( MediaType.APPLICATION_JSON ).body( exception.getLocalizedMessage() );

    }
..}

这是我的配置:

@ComponentScan
@EnableAutoConfiguration
@EnableGlobalMethodSecurity(securedEnabled = true)
@SpringBootApplication
public class EDentalManager extends WebMvcConfigurerAdapter  {
...
}

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
 @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
          .addFilterAfter(new CSRFTokenGeneratorFilter(), CsrfFilter.class)
          ...
          .and()
          .formLogin()
          .loginPage("/loginPage")
          .permitAll()
          .loginProcessingUrl("/login")
          .defaultSuccessUrl("/?tab=success")
          .failureHandler(authenticationFailureHandler)
          .and()
          .logout().addLogoutHandler(logoutHandler).logoutRequestMatcher( new AntPathRequestMatcher("/logout"))
          .deleteCookies("JSESSIONID")
          .invalidateHttpSession(true).permitAll().and().csrf()
          .and()  
          .sessionManagement()
          .withObjectPostProcessor(new AdditionalStrategyPostProcessor(new CleanRegistry(sessionRegistry)))
           .sessionFixation().changeSessionId()
           .maximumSessions(1)
           .maxSessionsPreventsLogin(true)
           .expiredUrl("/login?expired" )
           .sessionRegistry(sessionRegistry )
           .and()
           .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
           .invalidSessionUrl("/")
           .and().authorizeRequests().anyRequest().authenticated();
    }
}

捕获Spring Security异常的最佳方法是什么,以便在会话过多,身份验证异常等情况下向用户发送消息?

根据最新发现

更新

public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    @Autowired
    private MessageSource messages;

    @Autowired
    private LocaleResolver localeResolver;

    @Override
    public void onAuthenticationFailure(final HttpServletRequest request, final HttpServletResponse response,
                                        final AuthenticationException exception) throws IOException, ServletException {

        final Locale locale = localeResolver.resolveLocale(request);
        String errorMessage = buildErrorMessage(response, exception, locale);
        response.setHeader("Authentication Error", errorMessage);
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.sendError(HttpStatus.UNAUTHORIZED.value(), errorMessage);
    }

    private void buildErrorMessage(final HttpServletResponse response, Exception exception, Locale locale) {

               String errorMessage = messages.getMessage("message.badCredentials", null, locale);
    response.setStatus(HttpStatus.UNAUTHORIZED.value());

    if (exception instanceof BadCredentialsException) {
        errorMessage = messages.getMessage("auth.message.invalid.credentials", null, locale);
    } else if (exception.getMessage().equalsIgnoreCase("User is disabled")) {
        errorMessage = messages.getMessage("auth.message.disabled", null, locale);
    } else if (exception.getMessage().equalsIgnoreCase("User account has expired")) {
        errorMessage = messages.getMessage("auth.message.expired", null, locale);
    } else if (exception.getMessage().equalsIgnoreCase("blocked")) {
        errorMessage = messages.getMessage("auth.message.blocked", null, locale);
    } else {
        errorMessage = exception.getMessage();
    }
}

我的/ login POST后我现在被重定向到error.html,我看到了一个401 ResponseStatus,我有我在响应上的标题信息。

这似乎应该在没有重定向和ResponseEntity的情况下处理,但这并不像Spring Boot&安全处理它。任何人都可以在不使用Thymeleaf(我们是纯粹的http - > json - > Tomcat)的情况下建议更清晰地处理此消息身份验证事件吗?

0 个答案:

没有答案