Spring Security with basic auth redirecting to /error for invalid credentials

一个人想着一个人 提交于 2019-11-30 20:41:51

I created a sample Spring Boot app, with the following security config:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("test").password("password").roles("USER");
    }

    @Bean
    public AuthenticationEntryPoint authenticationEntryPoint() {
        return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.headers().httpStrictTransportSecurity().xssProtection()
                .and().authorizeRequests().anyRequest().fullyAuthenticated()
                .and().csrf().disable();

        http.httpBasic().authenticationEntryPoint(authenticationEntryPoint());
        http.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint());

    }
}

When entering an invalid username/password (anything other than test/password), I get the following response:

{"timestamp":1439381390204,"status":401,"error":"Unauthorized","message":"Bad credentials","path":"/"}

This error is returned by org.springframework.boot.autoconfigure.web.BasicErrorController class, which if you have a look does define two methods with @RequestMapping("/error") - errorHtml and error. Since you're building an API, it's the second one that should be invoked and I would say that's the "correct" behaviour!

So, first thing, check that you're getting to the BasicErrorController when authentication fails. If you are, make sure that you're hitting the error method NOT errorHtml.

If none of the above proves helpful, check whether someone has overriden the default behaviour of the error controller. One common (and valid) extension is to implement your own org.springframework.boot.autoconfigure.web.ErrorAttributes to change the default error payload. But it's just as easy to replace the entire BasicErrorController with a non-standard implementation, so check for that in your application.

If all else fails and you're adamant that you want to disable Spring's default error handling (which I don't recommend), try adding this to your configuration:

@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})

What this will do is ensure that the error controllers are not loaded into the application context.

I think instead of http.exceptionHandling().authenticationEntryPoint you should be using http.httpBasic().authenticationEntryPoint. For form based authentication, this is working for me:

http
    .formLogin()
        .failureHandler(authenticationFailureHandler())
        ...
    ...

For the authentication failure handler, Spring's SimpleUrlAuthenticationFailureHandler can be used. When instantiated without any parameter, it would do what we want:

@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
    return new SimpleUrlAuthenticationFailureHandler();
}   

This is my complete security config file, in case it's helpful.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!