401 而不是 403 与弹簧靴 2

使用Spring Boot 1.5.6.RELEASE,我能够发送HTTP状态代码,而不是如如何让spring安全响应未经授权(http 401代码)中所述,如果请求uri而不进行身份验证,通过这样做:401403

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,发现不再有这样的类(至少在那个软件包中)。

问题:

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

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


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


答案 1

小心

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

如果您放置一些自定义配置来修改安全机制行为,则此情况可能会更改。如果是这种情况,并且您确实需要强制状态,请阅读下面的原始帖子。401

原始帖子

该类已被删除,取而代之的是 。org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPointorg.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));
        //...
    }
}

答案 2

只是为了详细说明@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


推荐