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
相关产品推荐
相关产品推荐

