繁体   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