无法在4.0 spring安全性中设置自定义身份验证失败处理程序

时间:2015-10-15 12:36:20

标签: spring-security

我想在我的项目中设置自定义AuthenticationFailureHandler。即使我将authenticationFailureHandler配置如下,但在登录失败时也无法正确接收。

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

..................
@Inject
private AjaxAuthenticationFailureHandler ajaxAuthenticationFailureHandler;
..................

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .anyRequest().authenticated().and()
            .formLogin().loginPage("/signin").failureHandler(ajaxAuthenticationFailureHandler)
                .permitAll()
                .failureUrl("/signin")
                .defaultSuccessUrl("/search").and()
            .logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/signout"))
                .logoutSuccessUrl("/signin")
                .permitAll().and().csrf();
    }

我的自定义AuthenticationFailureHandler类

@Component
public class AjaxAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,
                                    AuthenticationException exception) throws IOException, ServletException {
        // Custom code
    }
}

当我调试应用程序时,方法onAuthenticationFailureSimpleUrlAuthenticationFailureHandler调用,但不在我的自定义AjaxAuthenticationFailureHandler中调用,即使我扩展了相同的SimpleUrlAuthenticationFailureHandler

解决问题可能是错误或错过任何配置?

2 个答案:

答案 0 :(得分:4)

在这种情况下,当我们设置自定义AjaxAuthenticationFailureHandler然后我们配置failureUrl("/signin")时,配置failureUrl("/signin")将使用新{{1}覆盖已配置的AjaxAuthenticationFailureHandler }}。

这是SimpleUrlAuthenticationFailureHandlerfailureUrl方法的实施,如failureHandler

AbstractAuthenticationFilterConfigurer

如果我们只设置如下 public abstract class AbstractAuthenticationFilterConfigurer<B extends HttpSecurityBuilder<B>, T extends AbstractAuthenticationFilterConfigurer<B, T, F>, F extends AbstractAuthenticationProcessingFilter> extends AbstractHttpConfigurer<T, B> { ........... private AuthenticationFailureHandler failureHandler; private String failureUrl; .......... public final T failureUrl(String authenticationFailureUrl) { T result = failureHandler(new SimpleUrlAuthenticationFailureHandler(authenticationFailureUrl)); this.failureUrl = authenticationFailureUrl; return result; } public final T failureHandler(AuthenticationFailureHandler authenticationFailureHandler) { this.failureUrl = null; this.failureHandler = authenticationFailureHandler; return getSelf(); } } ,我们将设置自定义AjaxAuthenticationFailureHandler。

failurehandler

如果我们要设置失败网址,我们可以使用 .formLogin().loginPage("/signin") .permitAll() .failureHandler(ajaxAuthenticationFailureHandler) .defaultSuccessUrl("/search").and() 在自定义AjaxAuthenticationFailureHandler中设置它,该setDefaultFailureUrl(String defaultFailureUrl)是从其父类SimpleUrlAuthenticationFailureHandler派生的。

答案 1 :(得分:0)

您可以在AjaxAuthenticationFailureHandler类中创建构造函数,并将defaultFailureUrl参数向下传递给您扩展的父级(SimpleUrlAuthenticationFailureHandler)。您的AjaxAuthenticationFailureHandler课程如下: -

@Component
public class AjaxAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {

    public AjaxAuthenticationFailureHandler (String defaultFailureUrl) {
        super(defaultFailureUrl);
    }

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, 
                                        HttpServletResponse response,
                                        AuthenticationException exception) throws IOException, ServletException {
        // Custom code
    }
}

您的配置块将如下所示: -

    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .anyRequest().authenticated().and()
            .formLogin()
                .loginPage("/signin")
                .failureHandler(new AjaxAuthenticationFailureHandler("/signin?auth=failure") // or whatever is a sensible url
                .permitAll()
                .defaultSuccessUrl("/search").and()

               ... 

请注意,将"/signin?auth=failure"添加到authorizeRequests()部分非常重要,否则控制器将不会选择auth参数,例如。

    .and()
        .authorizeRequests()
            .antMatchers(
                "/css/**", 
                "/js/**", 
                "/images/**", 
                "/signin**"          // REALLY IMPORTANT !!!
            ).permitAll()

有关详细信息,请参阅https://stackoverflow.com/a/39618113/1692179

您的控制器现在可以检查auth参数,例如

@Controller
public class SigninController 

    @RequestMapping(value="/login", method = RequestMethod.GET)
    public String handleError (Model model, 
                               @RequestParam(name = "auth", required = false) String auth) {
        if ("error".equals(auth)) {
            model.addAttribute("error", "invalid username/password");
        }

        return "login";
    }
}

希望这有帮助! : - )