[英]401 instead of 403 with Spring Boot 2
使用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"));
//...
}
}
使用org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint
class。
我刚刚升级到Spring Boot 2.0.0.RELEASE ,发现不再有这样的 class(至少在那个包中)。
问题:
这个 class ( Http401AuthenticationEntryPoint
) 是否存在于 Spring Boot 中?
如果不是,为了与依赖于此状态代码( 401
)而不是403
的其他实现保持一致,在现有项目中保持相同行为的好的替代方法是什么?
请注意,这与Spring Security anonymous 401 而不是 403不同,因为它专门指的是 SpringBoot 2 (该帖子中的解决方案不再适用于 SpringBoot 版本 2,或者根本不需要其他解决方案)
默认情况下,当spring-boot-starter-security
添加为依赖项并执行未经授权的请求时,Spring Boot 2 将返回401
。
如果您放置一些自定义配置来修改安全机制行为,这可能会改变。 如果是这种情况,并且您确实需要强制使用401
状态,请阅读下面的原始帖子。
类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));
//...
}
}
奖金
如果您需要在响应正文中返回一些信息或以某种方式自定义响应,您可以执行以下操作:
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));
//...
}
}
只是为了详细说明@lealceldeiro 的回答:
在 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);
}
//...
}
现在在 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 Boot Github Repo > PR Remove Http401AuthenticationEntryPoint 中的此评论。
Http401AuthenticationEntryPoint
已删除。
请参阅Spring Boot Github Repo > 问题#10715 (删除 Http401AuthenticationEntryPoint):
删除 Http401AuthenticationEntryPoint
rwinch 于 2017 年 10 月 20 日发表评论
据我所知,它没有在 Spring Boot 代码库中使用,因此删除Http401AuthenticationEntryPoint
可能会很好。
根据您的要求,您可以使用:
对于反应式 (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
}
}
您可以通过覆盖类 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.