[英]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.