为何Spring Security未阻止USER角色的POST请求?
问题:普通USER角色用户可执行需ADMIN权限的POST请求
背景配置
- 用户权限配置
@Bean public UserDetailsService uds() { UserDetails admin = User.builder() .username("admin") .password(encoder().encode("pwa")) .roles("ADMIN") .build(); UserDetails user = User.builder() .username("user") .password(encoder().encode("pwu")) .roles("USER") .build(); return new InMemoryUserDetailsManager(admin, user); }
- Repository配置
@RepositoryRestResource public interface CountryRepo extends CrudRepository<Country, Long> { }
- SecurityFilterChain配置
@Bean SecurityFilterChain configureSecurityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authCustomizer -> authCustomizer .requestMatchers("/api/countries").permitAll() .requestMatchers("/h2").permitAll() .requestMatchers(HttpMethod.POST, "/api/countries").hasRole("ADMIN") // 预期仅ADMIN可访问 .anyRequest().authenticated() ) .csrf().disable() .httpBasic(withDefaults()); http.headers().frameOptions().disable(); return http.build(); }
问题现象
配置中明确要求POST /api/countries仅允许ADMIN角色访问,但实际测试中,拥有USER角色的user用户也能成功发起该POST请求并创建国家,未返回预期的401/403状态码。
原因分析
Spring Security的授权规则是按定义顺序匹配,优先执行第一个匹配的规则。
当前配置中,.requestMatchers("/api/countries").permitAll()这条规则会匹配所有HTTP方法的/api/countries请求(包括POST),并且直接允许所有访问。后面的.requestMatchers(HttpMethod.POST, "/api/countries").hasRole("ADMIN")规则因为前面的规则已经匹配成功,根本不会被执行。
解决办法
调整规则顺序,将更具体、权限要求更高的规则放在通用规则前面,或者给通用规则指定HTTP方法,避免覆盖后续的特定规则。
方案1:调整规则顺序,优先匹配POST请求
@Bean SecurityFilterChain configureSecurityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authCustomizer -> authCustomizer .requestMatchers("/h2").permitAll() // 先匹配POST请求的权限规则 .requestMatchers(HttpMethod.POST, "/api/countries").hasRole("ADMIN") // 再允许GET请求的访问 .requestMatchers(HttpMethod.GET, "/api/countries").permitAll() .anyRequest().authenticated() ) .csrf().disable() .httpBasic(withDefaults()); http.headers().frameOptions().disable(); return http.build(); }
方案2:给通用规则指定HTTP方法
如果原本的/api/countries仅想开放GET访问,直接修改规则:
.requestMatchers(HttpMethod.GET, "/api/countries").permitAll() .requestMatchers(HttpMethod.POST, "/api/countries").hasRole("ADMIN")
这样POST请求会匹配到对应的ADMIN权限规则,USER角色用户发起请求时会返回403状态码,符合预期。
内容的提问来源于stack exchange,提问作者TMOTTM
相关产品推荐
相关产品推荐

