[英]401 instead of 403 with Spring Boot 2
With Spring Boot 1.5.6.RELEASE I was able to send HTTP Status code 401
instead of 403
as described in How let spring security response unauthorized(http 401 code) if requesting uri without authentication , by doing this:使用Spring Boot 1.5.6.RELEASE我能够发送 HTTP 状态代码
401
而不是403
,如How let spring security response unauthorized(http 401 code) if requesting uri without authentication中所述,方法是:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//...
http.exceptionHandling()
.authenticationEntryPoint(new Http401AuthenticationEntryPoint("myHeader"));
//...
}
}
using the org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
class.使用
org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
class。
I just upgraded to Spring Boot 2.0.0.RELEASE and found there is not such class any more (at least in that package).我刚刚升级到Spring Boot 2.0.0.RELEASE ,发现不再有这样的 class(至少在那个包中)。
Questions:问题:
Does this class ( Http401AuthenticationEntryPoint
) exist yet in Spring Boot?这个 class (
Http401AuthenticationEntryPoint
) 是否存在于 Spring Boot 中?
If no, what could be a good alternative for keeping the same behavior in an existing project in order to keep consistency with other implementations which depend on this status code ( 401
) instead of 403
?如果不是,为了与依赖于此状态代码(
401
)而不是403
的其他实现保持一致,在现有项目中保持相同行为的好的替代方法是什么?
Please notice this is different from Spring Security anonymous 401 instead of 403 because it's referring specifically to SpringBoot 2 (there are solutions in that post not applicable anymore in SpringBoot version 2 or others are not needed at all)请注意,这与Spring Security anonymous 401 而不是 403不同,因为它专门指的是 SpringBoot 2 (该帖子中的解决方案不再适用于 SpringBoot 版本 2,或者根本不需要其他解决方案)
By default Spring Boot 2 will return 401
when spring-boot-starter-security
is added as a dependency and an unauthorized request is performed.默认情况下,当
spring-boot-starter-security
添加为依赖项并执行未经授权的请求时,Spring Boot 2 将返回401
。
This may change if you place some custom configurations to modify the security mechanism behavior.如果您放置一些自定义配置来修改安全机制行为,这可能会改变。 If that's the case and you truly need to force the
401
status, then read the below original post.如果是这种情况,并且您确实需要强制使用
401
状态,请阅读下面的原始帖子。
The class org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
was removed in favor of org.springframework.security.web.authentication.HttpStatusEntryPoint
.类
org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
被移除,取而代之的是org.springframework.security.web.authentication.HttpStatusEntryPoint
。
In my case the code would go like this:在我的情况下,代码将是这样的:
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
//...
http.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED));
//...
}
}
Bonus奖金
If you need to return some information in the response body or customize the response somehow you can do something like this:如果您需要在响应正文中返回一些信息或以某种方式自定义响应,您可以执行以下操作:
1- Extend AuthenticationEntryPoint
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- Provide an instance of MyEntryPoint
to the security configuration 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));
//...
}
}
Just to elaborate @lealceldeiro's answer:只是为了详细说明@lealceldeiro 的回答:
Before Spring Boot 2 my Securiy Configuration class looked like this:在 Spring Boot 2 之前,我的安全配置类如下所示:
@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);
}
//...
}
And now in Spring Boot 2 it looks like this:现在在 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));
}
//...
}
See also this comment in Spring Boot Github Repo > PR Remove Http401AuthenticationEntryPoint .另请参阅Spring Boot Github Repo > PR Remove Http401AuthenticationEntryPoint 中的此评论。
Http401AuthenticationEntryPoint
was removed. Http401AuthenticationEntryPoint
已删除。
See Spring Boot Github Repo > Issue #10715 (Remove Http401AuthenticationEntryPoint):请参阅Spring Boot Github Repo > 问题#10715 (删除 Http401AuthenticationEntryPoint):
Remove Http401AuthenticationEntryPoint
删除 Http401AuthenticationEntryPoint
rwinch commented on 20 Oct 2017
rwinch 于 2017 年 10 月 20 日发表评论
As far as I can tell it is not being used in the Spring Boot code base, so it might be good to removeHttp401AuthenticationEntryPoint
.据我所知,它没有在 Spring Boot 代码库中使用,因此删除
Http401AuthenticationEntryPoint
可能会很好。
Depending on your requirements, you could use:根据您的要求,您可以使用:
For reactive (WebFlux) stack you can override the returned status code by adding such @Bean to catch some specific exceptions:对于反应式 (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
}
}
You can customize your logic with overriding the class AuthenticationEntryPoint this should be working:您可以通过覆盖类 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\"}");
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.