簡體   English   中英

401 而不是 403 Spring Boot 2

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM