Spring Boot 2:如果附加了授权标头,基本 Http Auth 会导致未受保护的端点响应 401“未经授权”

Ano*_*zzz 5 java spring spring-security spring-boot

迁移到 Spring Boot 2 并添加执行器和另一个应用程序控制端点的基本授权要求后,不可能使用授权标头调用任何不受保护的端点。

配置片段:

@Override
public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests()
            .requestMatchers(EndpointRequest.to("shutdown")).fullyAuthenticated()
            .antMatchers("/payment/status/*").fullyAuthenticated()
            .and().httpBasic();
}
Run Code Online (Sandbox Code Playgroud)

例如,使用“授权:基本...”调用 .../health 将导致 401“未经授权”,即使它不受 Spring Security 保护。

问题:如何调整配置,以便可以将带有授权标头的请求发送到任何不受保护的端点而不被拒绝?

UPD:此修复按我想要的方式工作

@Override
public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests()
            .requestMatchers(EndpointRequest.to("shutdown")).fullyAuthenticated()
            .antMatchers("/payment/status/*").fullyAuthenticated()
            .antMatchers("/payment/**").permitAll()
            .and().httpBasic();
}
Run Code Online (Sandbox Code Playgroud)

UPD2:没关系,刚刚测试了另一个请求,仍然收到 401“未经授权”。

curl localhost:8080/payment/<any_endpoint> -H "Authorization: Basic asdadas"
{"code":401,"message":"Unauthorized"}
Run Code Online (Sandbox Code Playgroud)

不幸的是,这种方法会覆盖 HttpSecurity 匹配器,例如:/ payment/ 变得可访问

@Override
public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()
            .authorizeRequests()
            .requestMatchers(EndpointRequest.to("shutdown")).fullyAuthenticated()
            .antMatchers("/payment/status/*").fullyAuthenticated()
            .and().httpBasic();
}

@Override
public void configure(WebSecurity webSecurity) throws Exception {
    webSecurity.ignoring().antMatchers("/payment/**");
}
Run Code Online (Sandbox Code Playgroud)

UPD 3:我创建了一个简单的项目,重现了这个问题 https://github.com/Anoobizzz/SpringSecurity2BasicAuthDemo

  1. /internal 和 /shutdown 只能由用户访问:P455W0RD
  2. /excessed 未经授权可访问
  3. /exposed 标头“Authorization: Basic 123123”响应 401“Unauthorized”

Zar*_*lis 4

通过调用.authorizeRequests(),您可以强制对所有这些请求进行授权,因为您没有调用.ignore()某些匹配器。

ignore我建议在匹配器上使用**,然后在允许所有层之上对指定匹配器逐步强制授权,以便除了明确指定的匹配器之外的所有内容都可以访问。

这可以完成您想要做的事情,但请注意,这不是最佳实践,原因很充分:您应该默认拒绝所有未经授权的流量,并且只明确允许对特定路由模板的未经授权的请求。

也就是说,明智的做法是在ignore您希望无需身份验证即可访问的路由上显式使用,而不仅仅是**(例如仅用于/home - /about - /login - /signup