Spring Security:所有端点返回状态 200 并且对约束没有响应作为 antMatchers

Posted

技术标签:

【中文标题】Spring Security:所有端点返回状态 200 并且对约束没有响应作为 antMatchers【英文标题】:Spring Security: all endpoints return status 200 and unresponsive to constraints as antMatchers 【发布时间】:2021-10-13 23:16:43 【问题描述】:

我想根据角色限制endpoints 的使用:admin/user

所以我正在尝试使用NoOpPasswordEncoder 实现Spring Security(用于测试目的), 但问题是: 所有端点都返回状态200 并且对约束无响应为antMatchers

澄清一下:我想以user 登录并因为antMatcher 而出现错误:

.antMatchers("/api/addresses")
.hasAuthority("ROLE_ADMIN")

但我现在使用当前配置得到200

我已经测试了Spring Security 格式的配置:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(inMemoryUserDetailsManager());
    

    @Bean
    public InMemoryUserDetailsManager inMemoryUserDetailsManager() 
        final Properties users = new Properties();
        users.put("admin","noopadmin,ROLE_ADMIN,enabled");
        users.put("user","noopuser,ROLE_USER,enabled");
        return new InMemoryUserDetailsManager(users);
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/addresses")
                .access("hasAuthority('ROLE_ADMIN')")
                .antMatchers("/api/address/**")
                .access("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_USER')")
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    

基于example config。

在调查时,我曾尝试发表评论,例如行:

.antMatchers("/api/address/**")
.access("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_USER')")

检查发生了什么并在以用户身份登录时仍然收到200

我也尝试过使用hasAuthority() 方法,例如:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(inMemoryUserDetailsManager());
    

    @Bean
    public InMemoryUserDetailsManager inMemoryUserDetailsManager() 
        final Properties users = new Properties();
        users.put("ADMIN","noopadmin,ROLE_ADMIN,enabled");
        users.put("USER","noopuser,ROLE_USER,enabled");
        return new InMemoryUserDetailsManager(users);
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers("/api/addresses")
                .hasAuthority("ROLE_ADMIN")
                .antMatchers("/api/address/**")
                .hasAnyAuthority("ROLE_ADMIN", "ROLE_USER")
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    

遵循correct order 和antMatchers(),当更具体的规则必须首先执行时,但它仍然对我没有帮助。

有人知道我在这里缺少什么吗?提前感谢您的任何想法。

UPD #1:

我尝试在 Postman 中使用 clear cookies,以用户身份登录,但我仍然收到 200

只有当我在 Postman 中不使用 Basic Auth 来处理 GET 请求时,我才会收到 401

UPD #2:

我已经使用不同版本的技术重现了这个问题:

Java 11 spring-boot-starter-parent 2.5.3 spring-boot-starter-security 2.5.3

【问题讨论】:

我在示例应用程序中尝试了提供的配置,它按预期工作,即对 /api/addresses 的请求返回 401。需要检查的几件事:1)您从哪里发出请求?是否有可能缓存凭据? 2)您还有其他安全配置吗? 我使用了curl localhost:8080/api/addresses。如果您使用 Postman,请确保在发出请求之前清除所有 cookie。 感谢您的澄清。请求 curl -u user:user localhost:8080/api/addresses 时,我收到了 403 响应。这是您期望的行为吗?使用您所期望的行为来更新问题将是有益的,因为目前尚不清楚。 感谢您的更新。我仍然收到来自curl -u user:user localhost:8080/api/addresses 和 Postman 的 403 回复。尝试从命令行发出请求,看看是否得到 403。如果这不起作用,请尝试创建一个新项目并逐个添加配置,看看哪个会破坏功能。 SecurityConfiguration 中的所有内容对我来说都很好。 由于 CORS,您最有可能获得 403。将来,请为 Spring Security 启用 DEBUG 日志(使用 google),日志将准确告诉您为什么会收到各种状态代码。 【参考方案1】:

原因及解决方法:


问题的原因冗余配置option:

server.servlet.context-path=/api

因为/api前缀已经存在于.antMatchers()


解决方案 #1:

为了修复它,我已将其从 application.properties 文件中删除,并将此前缀直接添加到端点。


解决方案 #2: 反过来也可以解决:去掉antMatchers()中的前缀/api并离开:

server.servlet.context-path=/api

使用application.properties


解决方案 #3:

我也用另一种配置解决了这个问题:

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter 

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(inMemoryUserDetailsManager());
    

    @Bean
    public InMemoryUserDetailsManager inMemoryUserDetailsManager() 
        final Properties users = new Properties();
        users.put("admin","noopadmin,ROLE_ADMIN,enabled");
        users.put("user","noopuser,ROLE_USER,enabled");
        return new InMemoryUserDetailsManager(users);
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.csrf().disable()
                .authorizeRequests()
                .anyRequest()
                .permitAll()
                .and()
                .httpBasic()
                .and()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    

在控制器方法上添加annotations:

@PreAuthorize("hasAuthority('ROLE_ADMIN')") 

因此:

@PreAuthorize("hasAuthority('ROLE_ADMIN') or hasAuthority('ROLE_USER')")

结果我得到的是403 而不是200

【讨论】:

以上是关于Spring Security:所有端点返回状态 200 并且对约束没有响应作为 antMatchers的主要内容,如果未能解决你的问题,请参考以下文章

如何忽略 Spring Security 中的端点?

如何在Spring Security中忽略端点?

REST端点身份验证的Spring Security意外行为?

Spring-Security:AuthenticationManager 抛出 BadCredentialsException 时返回状态 401

Spring Security - 只允许带有前缀的请求

Spring Security 配置访问