Spring 安全性,基本身份验证重定向到 /error 以获取无效凭据
Spring Security with basic auth redirecting to /error for invalid credentials
我有一个 spring 引导应用程序 运行 spring 使用基本身份验证的安全性。
当提供正确的基本身份验证凭据时,一切都很好,但是对于不正确的身份验证凭据,spring 会出现 HttpRequestMethodNotSupportedException: Request method 'POST' not supported
异常。
根据日志,spring 已识别身份验证失败,但结果并非如此。
2015-08-12 09:33:10.922 INFO 16988 --- [nio-8080-exec-4] o.s.b.a.audit.listener.AuditListener : AuditEvent [timestamp=Wed Aug 12 09:33:10 AEST 2015, principal=anonymousUser, type=AUTHORIZATION_FAILURE, data={type=org.springframework.security.access.AccessDeniedException, message=Access is denied}]
2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Bound request context to thread: FirewalledRequest[ org.apache.catalina.core.ApplicationHttpRequest@483e1fc6]
2015-08-12 09:33:10.927 DEBUG 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing POST request for [/myapplication/error]
2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Testing handler map [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@331bb032] in DispatcherServlet with name 'dispatcherServlet'
2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.w.s.handler.SimpleUrlHandlerMapping : No handler mapping found for [/error]
2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Testing handler map [org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping@69e79b9b] in DispatcherServlet with name 'dispatcherServlet'
2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Testing handler map [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping@27cc0354] in DispatcherServlet with name 'dispatcherServlet'
2015-08-12 09:33:10.927 DEBUG 16988 --- [nio-8080-exec-4] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /error
2015-08-12 09:33:10.928 DEBUG 16988 --- [nio-8080-exec-4] .m.m.a.ExceptionHandlerExceptionResolver : Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
使用上述日志并在调试 spring 源后,我发现在确定凭据不正确后,spring 创建了一个 BadCredentials 异常,然后尝试重定向到“/error ”,这种重定向是导致 HttpMethodNotAllowed 异常的原因。(我的应用程序没有 /error 端点)。
我试图告诉 spring 不要通过配置以下内容使用 /error,
`public class ServerCustomization 扩展了 ServerProperties {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
super.customize(container);
container.addErrorPages(new ErrorPage(HttpStatus.UNAUTHORIZED, null));
}`
这将使 spring 停止吐出 HttpMethodnotallowed 异常并使其产生 401(未授权),但我的异常处理程序未捕获我的异常(使用 @ControllerAdvice
配置).
我也试过像下面这样配置自定义身份验证入口点,但没有成功。
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
AlwaysSendUnauthorized401AuthenticationEntryPoint alwaysSendUnauthorized401AuthenticationEntryPoint =
new AlwaysSendUnauthorized401AuthenticationEntryPoint();
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().httpStrictTransportSecurity().xssProtection().and().authorizeRequests().anyRequest().fullyAuthenticated()
.and().csrf().disable();
http.exceptionHandling().authenticationEntryPoint(alwaysSendUnauthorized401AuthenticationEntryPoint);
}
public class AlwaysSendUnauthorized401AuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public final void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
}
有什么方法可以指定 spring 不重定向到 /error 和 return Bad Credentials Exception 吗?
我认为您应该使用 http.httpBasic().authenticationEntryPoint
而不是 http.exceptionHandling().authenticationEntryPoint
。对于基于表单的身份验证,这对我有用:
http
.formLogin()
.failureHandler(authenticationFailureHandler())
...
...
对于身份验证失败处理程序,可以使用 Spring 的 SimpleUrlAuthenticationFailureHandler
。在没有任何参数的情况下实例化时,它将执行我们想要的操作:
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
return new SimpleUrlAuthenticationFailureHandler();
}
This 是我完整的安全配置文件,以备不时之需。
我创建了一个示例 Spring 启动应用程序,具有以下安全配置:
@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());
}
}
当输入无效的 username/password(除 test/password 之外的任何值)时,我得到以下响应:
{"timestamp":1439381390204,"status":401,"error":"Unauthorized","message":"Bad credentials","path":"/"}
此错误由 org.springframework.boot.autoconfigure.web.BasicErrorController
class 返回,如果您看一下,它确实定义了两个方法 @RequestMapping("/error")
- errorHtml
和 error
。由于您正在构建一个 API,它是应该调用的第二个,我会说这就是 "correct" 行为!
因此,首先,检查您是否在身份验证失败时进入 BasicErrorController
。如果是,请确保您使用的是 error
方法而不是 errorHtml
.
如果上述 none 证明有帮助,请检查是否有人覆盖了错误控制器的默认行为。一种常见(且有效)的扩展是实现您自己的 org.springframework.boot.autoconfigure.web.ErrorAttributes
以更改默认错误负载。但是用非标准实现替换整个 BasicErrorController
也同样容易,因此请在您的应用程序中检查一下。
如果所有其他方法都失败并且您坚持要禁用 Spring 的默认错误处理(我不推荐),请尝试将其添加到您的配置中:
@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})
这将确保错误控制器不会加载到应用程序上下文中。
我有一个 spring 引导应用程序 运行 spring 使用基本身份验证的安全性。
当提供正确的基本身份验证凭据时,一切都很好,但是对于不正确的身份验证凭据,spring 会出现 HttpRequestMethodNotSupportedException: Request method 'POST' not supported
异常。
根据日志,spring 已识别身份验证失败,但结果并非如此。
2015-08-12 09:33:10.922 INFO 16988 --- [nio-8080-exec-4] o.s.b.a.audit.listener.AuditListener : AuditEvent [timestamp=Wed Aug 12 09:33:10 AEST 2015, principal=anonymousUser, type=AUTHORIZATION_FAILURE, data={type=org.springframework.security.access.AccessDeniedException, message=Access is denied}]
2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Bound request context to thread: FirewalledRequest[ org.apache.catalina.core.ApplicationHttpRequest@483e1fc6]
2015-08-12 09:33:10.927 DEBUG 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing POST request for [/myapplication/error]
2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Testing handler map [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping@331bb032] in DispatcherServlet with name 'dispatcherServlet'
2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.w.s.handler.SimpleUrlHandlerMapping : No handler mapping found for [/error]
2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Testing handler map [org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping@69e79b9b] in DispatcherServlet with name 'dispatcherServlet'
2015-08-12 09:33:10.927 TRACE 16988 --- [nio-8080-exec-4] o.s.web.servlet.DispatcherServlet : Testing handler map [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping@27cc0354] in DispatcherServlet with name 'dispatcherServlet'
2015-08-12 09:33:10.927 DEBUG 16988 --- [nio-8080-exec-4] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /error
2015-08-12 09:33:10.928 DEBUG 16988 --- [nio-8080-exec-4] .m.m.a.ExceptionHandlerExceptionResolver : Resolving exception from handler [null]: org.springframework.web.HttpRequestMethodNotSupportedException: Request method 'POST' not supported
使用上述日志并在调试 spring 源后,我发现在确定凭据不正确后,spring 创建了一个 BadCredentials 异常,然后尝试重定向到“/error ”,这种重定向是导致 HttpMethodNotAllowed 异常的原因。(我的应用程序没有 /error 端点)。
我试图告诉 spring 不要通过配置以下内容使用 /error,
`public class ServerCustomization 扩展了 ServerProperties {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
super.customize(container);
container.addErrorPages(new ErrorPage(HttpStatus.UNAUTHORIZED, null));
}`
这将使 spring 停止吐出 HttpMethodnotallowed 异常并使其产生 401(未授权),但我的异常处理程序未捕获我的异常(使用 @ControllerAdvice
配置).
我也试过像下面这样配置自定义身份验证入口点,但没有成功。
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
AlwaysSendUnauthorized401AuthenticationEntryPoint alwaysSendUnauthorized401AuthenticationEntryPoint =
new AlwaysSendUnauthorized401AuthenticationEntryPoint();
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().httpStrictTransportSecurity().xssProtection().and().authorizeRequests().anyRequest().fullyAuthenticated()
.and().csrf().disable();
http.exceptionHandling().authenticationEntryPoint(alwaysSendUnauthorized401AuthenticationEntryPoint);
}
public class AlwaysSendUnauthorized401AuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public final void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
}
}
有什么方法可以指定 spring 不重定向到 /error 和 return Bad Credentials Exception 吗?
我认为您应该使用 http.httpBasic().authenticationEntryPoint
而不是 http.exceptionHandling().authenticationEntryPoint
。对于基于表单的身份验证,这对我有用:
http
.formLogin()
.failureHandler(authenticationFailureHandler())
...
...
对于身份验证失败处理程序,可以使用 Spring 的 SimpleUrlAuthenticationFailureHandler
。在没有任何参数的情况下实例化时,它将执行我们想要的操作:
@Bean
public AuthenticationFailureHandler authenticationFailureHandler() {
return new SimpleUrlAuthenticationFailureHandler();
}
This 是我完整的安全配置文件,以备不时之需。
我创建了一个示例 Spring 启动应用程序,具有以下安全配置:
@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());
}
}
当输入无效的 username/password(除 test/password 之外的任何值)时,我得到以下响应:
{"timestamp":1439381390204,"status":401,"error":"Unauthorized","message":"Bad credentials","path":"/"}
此错误由 org.springframework.boot.autoconfigure.web.BasicErrorController
class 返回,如果您看一下,它确实定义了两个方法 @RequestMapping("/error")
- errorHtml
和 error
。由于您正在构建一个 API,它是应该调用的第二个,我会说这就是 "correct" 行为!
因此,首先,检查您是否在身份验证失败时进入 BasicErrorController
。如果是,请确保您使用的是 error
方法而不是 errorHtml
.
如果上述 none 证明有帮助,请检查是否有人覆盖了错误控制器的默认行为。一种常见(且有效)的扩展是实现您自己的 org.springframework.boot.autoconfigure.web.ErrorAttributes
以更改默认错误负载。但是用非标准实现替换整个 BasicErrorController
也同样容易,因此请在您的应用程序中检查一下。
如果所有其他方法都失败并且您坚持要禁用 Spring 的默认错误处理(我不推荐),请尝试将其添加到您的配置中:
@EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})
这将确保错误控制器不会加载到应用程序上下文中。