17

使用Spring Boot 1.5.6.RELEASE,我能够发送 HTTP 状态代码401,而不是403如在未经身份验证的情况下请求 uri 时如何让 spring 安全响应未授权(http 401 代码)中所述,通过执行以下操作:

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类。

我刚刚升级到Spring Boot 2.0.0.RELEASE,发现不再有这样的类(至少在那个包中)。

问题:

  • 这个类 ( Http401AuthenticationEntryPoint) 在 Spring Boot 中是否存在?

  • 如果不是,那么在现有项目中保持相同行为以保持与依赖此状态代码 ( 401) 而不是 的其他实现的一致性的好选择是403什么?


请注意,这与Spring Security 匿名 401 而不是 403不同,因为它专门指的是 SpringBoot 2(该帖子中的解决方案在 SpringBoot 版本 2 中不再适用,或者根本不需要其他解决方案)

4

5 回答 5

32

小心

默认情况下401,当spring-boot-starter-security被添加为依赖项并执行未经授权的请求时, Spring Boot 2 将返回。

如果您放置一些自定义配置来修改安全机制行为,这可能会改变。如果是这种情况并且您确实需要强制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));
        //...
    }
}
于 2018-03-12T17:51:18.887 回答
3

只是为了详细说明@lealceldeiro 的答案:

在 Spring Boot 2 之前,我的 Securiy Configuration 类看起来像这样:

@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中的此评论

于 2018-10-25T10:12:32.847 回答
2

Http401AuthenticationEntryPoint去掉了。

请参阅Spring Boot Github存储库> 问题#10715(删除 Http401AuthenticationEntryPoint):

删除 Http401AuthenticationEntryPoint

rwinch 于 2017 年 10 月 20 日发表评论
据我所知,它没有在 Spring Boot 代码库中使用,因此删除Http401AuthenticationEntryPoint.

根据您的要求,您可以使用:

于 2018-10-17T14:53:14.167 回答
1

对于反应式(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
}
}
于 2022-02-10T10:16:19.130 回答
0

您可以通过覆盖应该有效的类 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\"}");
    }
}
于 2018-11-14T09:31:27.137 回答