You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Security中RequestMatcher匹配含QueryParam的端点失败求助

Spring Security带QueryParam的RequestMatcher配置解决方案

问题场景

在使用Spring Security搭建后端安全体系时,配置了QueryParam的端点/api/v1/companies/list?sortBy=ALPHABETICALLY无法通过requestMatchers正确匹配:未登录访问时抛出org.springframework.security.access.AccessDeniedException: Access Denied,登录后可正常访问;其他含URI路径参数的端点均配置正常。

相关代码片段:

SecurityFilterChain配置

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests((authorize) -> authorize
                    .requestMatchers(HttpMethod.GET, "/api/v1/students/{studentId}").permitAll()
                    .requestMatchers(HttpMethod.POST, "/api/v1/students").permitAll()
                    .requestMatchers(HttpMethod.GET, "/api/v1/companies/list?sortBy=" + CompanySortBy.ALPHABETICALLY).permitAll()
                    .requestMatchers(HttpMethod.GET,"/api/v1/companies/{companyId}").permitAll()
                    .requestMatchers(HttpMethod.GET, "/api/v1/companies/").permitAll()
                    .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2ResourceServer -> oauth2ResourceServer
                    .jwt(jwt -> jwt
                            .decoder(jwtDecoder())))
            .sessionManagement(session -> session
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .cors(Customizer.withDefaults());
    return http.build();
}

对应Controller方法

@GetMapping(path = {"/list"}, consumes =  MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity getAllCompanies(@RequestParam("sortBy") CompanySortBy sortBy) { 
    // Controller逻辑
}

问题原因

Spring Security默认的requestMatchers(String path)仅匹配请求的路径部分,不会解析Query参数。直接在路径字符串中拼接?sortBy=xxx会被当作路径的一部分,而实际请求的路径是/api/v1/companies/list,因此无法匹配成功。

解决方案

方法1:使用MvcRequestMatcher精确匹配Query参数

通过MvcRequestMatcher可以结合Spring MVC的路径解析规则,同时指定Query参数的匹配条件。需要注入HandlerMappingIntrospector来构建匹配器:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, HandlerMappingIntrospector introspector) throws Exception {
    // 构建MvcRequestMatcher构建器
    MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector);
    
    http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests((authorize) -> authorize
                    .requestMatchers(HttpMethod.GET, "/api/v1/students/{studentId}").permitAll()
                    .requestMatchers(HttpMethod.POST, "/api/v1/students").permitAll()
                    // 精确匹配路径+sortBy参数值
                    .requestMatchers(mvcMatcherBuilder
                            .pattern("/api/v1/companies/list")
                            .requestParam("sortBy", CompanySortBy.ALPHABETICALLY.name()))
                    .permitAll()
                    .requestMatchers(HttpMethod.GET,"/api/v1/companies/{companyId}").permitAll()
                    .requestMatchers(HttpMethod.GET, "/api/v1/companies/").permitAll()
                    .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2ResourceServer -> oauth2ResourceServer
                    .jwt(jwt -> jwt
                            .decoder(jwtDecoder())))
            .sessionManagement(session -> session
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .cors(Customizer.withDefaults());
    return http.build();
}

方法2:放行整个路径(无需限制Query参数)

如果不需要针对特定Query参数值放行,仅需允许访问/api/v1/companies/list路径,可直接简化配置:

.requestMatchers(HttpMethod.GET, "/api/v1/companies/list").permitAll()

关键说明

  • MvcRequestMatcher是Spring Security 6.x及以上版本推荐的匹配方式,与Spring MVC的路径解析逻辑一致,能准确匹配Controller的映射规则。
  • requestParam方法支持多种匹配方式:精确匹配值、正则匹配,或仅检查参数存在(不指定值)。

内容的提问来源于stack exchange,提问作者georgesgj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 21:42:46