401 而不是 403 Spring Boot 2
401 instead of 403 with Spring Boot 2
使用 Spring Boot 1.5.6.RELEASE I was able to send HTTP Status code 401
instead of 403
as described in ,通过这样做:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//...
http.exceptionHandling()
.authenticationEntryPoint(new Http401AuthenticationEntryPoint("myHeader"));
//...
}
}
使用 org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
class。
我刚刚升级到 Spring Boot 2.0.0.RELEASE,发现不再有这样的 class(至少在那个包中)。
问题:
这个 class (Http401AuthenticationEntryPoint
) 是否存在于 Spring 引导中?
如果否,为了与依赖此状态代码 (401
) 的其他实现保持一致,在现有项目中保持相同行为的良好替代方案可能是什么403
?
请注意这与 不同,因为它特指 SpringBoot 2(有解决方案 post 不是Spring启动版本 2 或其他版本不再适用)
注意
默认 Spring Boot 2 将 return 401
当 spring-boot-starter-security
被添加为依赖项并执行了未经授权的请求。
如果您放置一些自定义配置来修改安全机制行为,这可能会改变。如果是这种情况并且您确实需要强制 401
状态,请阅读下面的原文 post.
原版Post
class org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
已删除,取而代之的是 org.springframework.security.web.authentication.HttpStatusEntryPoint
。
在我的例子中,代码是这样的:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//...
http.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
//...
}
}
奖金
如果您需要 return 响应正文中的一些信息或以某种方式自定义响应,您可以这样做:
1- 扩展 AuthenticationEntryPoint
public class MyEntryPoint implements AuthenticationEntryPoint {
private final HttpStatus httpStatus;
private final Object responseBody;
public MyEntryPoint(HttpStatus httpStatus, Object responseBody) {
Assert.notNull(httpStatus, "httpStatus cannot be null");
Assert.notNull(responseBody, "responseBody cannot be null");
this.httpStatus = httpStatus;
this.responseBody = responseBody;
}
@Override
public final void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.setStatus(httpStatus.value());
try (PrintWriter writer = response.getWriter()) {
writer.print(new ObjectMapper().writeValueAsString(responseBody));
}
}
}
2- 向安全配置
提供MyEntryPoint
的实例
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// customize your response body as needed
Map<String, String> responseBody = new HashMap<>();
responseBody.put("error", "unauthorized");
//...
http.exceptionHandling()
.authenticationEntryPoint(new MyEntryPoint(HttpStatus.UNAUTHORIZED, responseBody));
//...
}
}
Http401AuthenticationEntryPoint
已删除。
请参阅 Spring 启动 Github Repo > 问题 #10715(删除 Http401AuthenticationEntryPoint):
Remove Http401AuthenticationEntryPoint
rwinch commented on 20 Oct 2017
As far as I can tell it is not being used in the Spring Boot code base, so it might be good to remove Http401AuthenticationEntryPoint
.
根据您的要求,您可以使用:
只是为了详细说明@lealceldeiro 的回答:
在 Spring 引导 2 之前,我的安全配置 class 如下所示:
@Configuration
public class MyConfig extends WebSecurityConfigurerAdapter {
@Bean
public Http401AuthenticationEntryPoint securityException401EntryPoint() {
return new Http401AuthenticationEntryPoint("Bearer realm=\"webrealm\"");
}
@Autowired
private Http401AuthenticationEntryPoint authEntrypoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
// some http configuration ...
// Spring Boot 1.5.x style
http.exceptionHandling().authenticationEntryPoint(authEntrypoint);
}
//...
}
现在 Spring Boot 2 看起来像这样:
@Configuration
public class MyConfig extends WebSecurityConfigurerAdapter {
//Bean configuration for Http401AuthenticationEntryPoint can be removed
//Autowiring also removed
@Override
protected void configure(HttpSecurity http) throws Exception {
// some http configuration ...
// Spring Boot 2 style
http.exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
}
//...
}
另请参见 Spring 中的 comment 启动 Github Repo > PR 删除 Http401AuthenticationEntryPoint .
您可以通过覆盖 class AuthenticationEntryPoint 来自定义您的逻辑
这应该有效:
@Component public class AuthEntryPointException implements AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = -8970718410437077606L;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
response.setContentType("application/json");
response.getWriter().write("{\"result\":\"UNAUTHORIZED\",\"message\":\"UNAUTHORIZED or Invalid Token\"}");
}
}
对于反应式 (WebFlux) 堆栈,您可以通过添加此类 @Bean 来捕获某些特定异常来覆盖返回的状态代码:
@Component
class MyErrorAttributes : DefaultErrorAttributes() {
override fun getErrorAttributes(
request: ServerRequest,
options: ErrorAttributeOptions
): MutableMap<String, Any> {
val cause = super.getError(request)
val errorAttributes = super.getErrorAttributes(request, options)
when (cause) {
is TokenExpiredException -> {
errorAttributes["status"] = HttpStatus.UNAUTHORIZED.value()
errorAttributes["error"] = HttpStatus.UNAUTHORIZED.reasonPhrase
}
}
return errorAttributes
}
}
使用 Spring Boot 1.5.6.RELEASE I was able to send HTTP Status code 401
instead of 403
as described in
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//...
http.exceptionHandling()
.authenticationEntryPoint(new Http401AuthenticationEntryPoint("myHeader"));
//...
}
}
使用 org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
class。
我刚刚升级到 Spring Boot 2.0.0.RELEASE,发现不再有这样的 class(至少在那个包中)。
问题:
这个 class (
Http401AuthenticationEntryPoint
) 是否存在于 Spring 引导中?如果否,为了与依赖此状态代码 (
401
) 的其他实现保持一致,在现有项目中保持相同行为的良好替代方案可能是什么403
?
请注意这与
注意
默认 Spring Boot 2 将 return 401
当 spring-boot-starter-security
被添加为依赖项并执行了未经授权的请求。
如果您放置一些自定义配置来修改安全机制行为,这可能会改变。如果是这种情况并且您确实需要强制 401
状态,请阅读下面的原文 post.
原版Post
class org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
已删除,取而代之的是 org.springframework.security.web.authentication.HttpStatusEntryPoint
。
在我的例子中,代码是这样的:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//...
http.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
//...
}
}
奖金
如果您需要 return 响应正文中的一些信息或以某种方式自定义响应,您可以这样做:
1- 扩展 AuthenticationEntryPoint
public class MyEntryPoint implements AuthenticationEntryPoint {
private final HttpStatus httpStatus;
private final Object responseBody;
public MyEntryPoint(HttpStatus httpStatus, Object responseBody) {
Assert.notNull(httpStatus, "httpStatus cannot be null");
Assert.notNull(responseBody, "responseBody cannot be null");
this.httpStatus = httpStatus;
this.responseBody = responseBody;
}
@Override
public final void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.setStatus(httpStatus.value());
try (PrintWriter writer = response.getWriter()) {
writer.print(new ObjectMapper().writeValueAsString(responseBody));
}
}
}
2- 向安全配置
提供MyEntryPoint
的实例
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// customize your response body as needed
Map<String, String> responseBody = new HashMap<>();
responseBody.put("error", "unauthorized");
//...
http.exceptionHandling()
.authenticationEntryPoint(new MyEntryPoint(HttpStatus.UNAUTHORIZED, responseBody));
//...
}
}
Http401AuthenticationEntryPoint
已删除。
请参阅 Spring 启动 Github Repo > 问题 #10715(删除 Http401AuthenticationEntryPoint):
Remove Http401AuthenticationEntryPoint
rwinch commented on 20 Oct 2017
As far as I can tell it is not being used in the Spring Boot code base, so it might be good to removeHttp401AuthenticationEntryPoint
.
根据您的要求,您可以使用:
只是为了详细说明@lealceldeiro 的回答:
在 Spring 引导 2 之前,我的安全配置 class 如下所示:
@Configuration
public class MyConfig extends WebSecurityConfigurerAdapter {
@Bean
public Http401AuthenticationEntryPoint securityException401EntryPoint() {
return new Http401AuthenticationEntryPoint("Bearer realm=\"webrealm\"");
}
@Autowired
private Http401AuthenticationEntryPoint authEntrypoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
// some http configuration ...
// Spring Boot 1.5.x style
http.exceptionHandling().authenticationEntryPoint(authEntrypoint);
}
//...
}
现在 Spring Boot 2 看起来像这样:
@Configuration
public class MyConfig extends WebSecurityConfigurerAdapter {
//Bean configuration for Http401AuthenticationEntryPoint can be removed
//Autowiring also removed
@Override
protected void configure(HttpSecurity http) throws Exception {
// some http configuration ...
// Spring Boot 2 style
http.exceptionHandling().authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
}
//...
}
另请参见 Spring 中的 comment 启动 Github Repo > PR 删除 Http401AuthenticationEntryPoint .
您可以通过覆盖 class AuthenticationEntryPoint 来自定义您的逻辑 这应该有效:
@Component public class AuthEntryPointException implements AuthenticationEntryPoint, Serializable {
private static final long serialVersionUID = -8970718410437077606L;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response,
AuthenticationException authException) throws IOException {
response.setStatus(HttpStatus.SC_UNAUTHORIZED);
response.setContentType("application/json");
response.getWriter().write("{\"result\":\"UNAUTHORIZED\",\"message\":\"UNAUTHORIZED or Invalid Token\"}");
}
}
对于反应式 (WebFlux) 堆栈,您可以通过添加此类 @Bean 来捕获某些特定异常来覆盖返回的状态代码:
@Component
class MyErrorAttributes : DefaultErrorAttributes() {
override fun getErrorAttributes(
request: ServerRequest,
options: ErrorAttributeOptions
): MutableMap<String, Any> {
val cause = super.getError(request)
val errorAttributes = super.getErrorAttributes(request, options)
when (cause) {
is TokenExpiredException -> {
errorAttributes["status"] = HttpStatus.UNAUTHORIZED.value()
errorAttributes["error"] = HttpStatus.UNAUTHORIZED.reasonPhrase
}
}
return errorAttributes
}
}