发布于 2年前

Spring Security自定义验证失败处理器AuthenticationFailureHandler

Spring Security的AuthenticationManager用来处理验证的请求,处理的结果分两种:

  • 验证成功:结果由AuthenticationSuccessHandler处理
  • 验证失败:结果由交给AuthenticationFailureHandler处理。

在Spring Security内置了几种验证失败处理器:

  • DelegatingAuthenticationFailureHandler将AuthenticationException子类委托给不同的AuthenticationFailureHandler,这意味着我们可以为AuthenticationException的不同实例创建不同的行为
  • ExceptionMappingAuthenticationFailureHandler根据AuthenticationException的完整类名将用户重定向到特定的URL
  • SimpleUrlAuthenticationFailureHandler是默认使用的组件,如果指定,它会将用户重定向到failureUrl;否则,它只会返回401响应

自定义AuthenticationFailureHandler

如果想自定义验证失败处理器,需要实现AuthenticationFailureHandler接口。AuthenticationFailureHandler接口源码如下:

package org.springframework.security.web.authentication;
public interface AuthenticationFailureHandler {
    /**
     * 认证失败时会调用此方法
     * @param request 出现认证失败时所处于的请求.
     * @param response 对应上面请求的响应对象.
     * @param exception 携带认证失败原因的认证失败异常对象
     * request.
     */
    void onAuthenticationFailure(HttpServletRequest request,
            HttpServletResponse response, AuthenticationException exception)
            throws IOException, ServletException;
}

实现一个简单的自定义AuthenticationFailureHandler,如下:

public class CustomAuthenticationFailureHandler 
  implements AuthenticationFailureHandler {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void onAuthenticationFailure(HttpServletRequest request,HttpServletResponse response,AuthenticationException exception) 
      throws IOException, ServletException {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        Map<String, Object> data = new HashMap<>();
        data.put("exception", exception.getMessage());
        response.getOutputStream().println(objectMapper.writeValueAsString(data));
    }
}

这里只是简单的返回了一个验证失败的http状态码401,并把异常信息返回。

配置自定义AuthenticationFailureHandler

Spring Security默认是使用SimpleUrlAuthenticationFailureHandler,在配置中修改为自定义的AuthenticationFailureHandler。

@Configuration
@EnableWebSecurity
public class SecurityConfiguration 
  extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) 
      throws Exception {
        auth
          .inMemoryAuthentication()
          .withUser("test")
          .password("test")
          .roles("USER");
    }
    @Override
    protected void configure(HttpSecurity http) 
      throws Exception {
        http
          .authorizeRequests()
          .anyRequest()
          .authenticated()
          .and()
          .formLogin()
          .failureHandler(customAuthenticationFailureHandler());
    }
    @Bean
    public AuthenticationFailureHandler customAuthenticationFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }
}

可以注意到在HttpSecurity上调用了failureHandler来配置自定义的AuthenticationFailureHandler.

©2020 edoou.com   京ICP备16001874号-3