简体   繁体   English

401 而不是 403 Spring Boot 2

[英]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,或者根本不需要其他解决方案)

Heads up抬头

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状态,请阅读下面的原始帖子。

Original Post原帖

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 remove Http401AuthenticationEntryPoint .据我所知,它没有在 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.

相关问题 Spring 启动 webflux 只返回 401 和 403 - Spring boot webflux only returning 401 and 403 Keycloak 401/403 HTTP 错误(弹簧启动) - Keycloak 401/403 HTTP Error (Spring Boot) Spring Security 匿名 401 而不是 403 - Spring Security anonymous 401 instead of 403 Spring安全性返回401/403而不是将用户重定向到登录页面 - Spring security return 401/403 instead of redirecting the user to the login page Spring Boot WebMvcTest 返回 302 而不是 GET 方法的 401 - Spring Boot WebMvcTest returns 302 instead of 401 for GET methods Spring boot - 返回403 Forbidden而不是重定向到登录页面 - Spring boot - return 403 Forbidden instead of redirect to login page 如何在 spring 引导中发送 400、401、405、403 和 500 错误的自定义响应? - How to send custom response for 400, 401, 405, 403 and 500 errors in spring boot? 使用Keycloak和Spring引导时如何自定义401 Unauthorized和403 Forbidden HTTP响应? - How to customize 401 Unauthorized and 403 Forbidden HTTP responses when using Keycloak and Spring boot? Spring Security 返回 403 而不是 401 并创建无效的 Redis 会话 cookie - Spring Security returns 403 instead of 401 and creates invalid Redis session cookie Spring Boot,Spring Security 返回状态 401 而不是 404,用于“未找到 HTTP 请求的映射” - Spring Boot, Spring Security returns a status 401 instead of 404 for "no mapping found for HTTP request"
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM