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

Spring Security 6中Request Matchers匹配含ID URL路径的问题

Spring Security 6中requestMatchers无法匹配含路径参数的URL问题

我正尝试升级到Spring Boot 3和Spring Security 6,之前用mvcMatchers可以正常匹配以下URL:

String[] companiesEndpoints = {"/companies", "/companies/*"};
String[] ideationEndpoint = {"/ideation", "/ideation/*"};
String[] assessmentsEndpoints = {"/assessment", "/assessment/*", "/assessment/*/value-rating", "/assessment/*/viability-rating", "/assessment/*/customer-rating"};
String[] teamsEndpoints = {"/teams", "/teams/*"};
String[] userEndpoints = {"/users", "/users/*"};
String[] projectEndpoints = {"/project", "/project/*", "/project-and-assessment"};
String[] workspaceEndpoints = {"/workspace", "/workspace/*"};
String[] tagEndpoints = {"/tag", "/tag/*"};

升级后mvcMatchers被requestMatchers替代,我原以为直接替换就能正常工作,但现在部分请求无法匹配。比如原本.mvcMatchers(assessmentsEndpoints).authenticated()可以匹配"/assessment/2900b695-d344-4bec-b25d-524f6b22a93a/customer-rating",换成.requestMatchers(assessmentsEndpoints).authenticated()后就匹配失败,API返回403。

显然requestMatcher并非mvcMatcher的直接替代品,我不清楚该如何构造端点让requestMatchers允许这类请求。我有很多含路径参数的请求,比如"/assessment/{assessmentId}/value-rating*",请问应该怎么构造String[]端点数组来匹配这类URL?

附完整的SecurityConfig类代码:

@Configuration
public class SecurityConfig {

    @Value(value = "${auth0.audience}")
    private String apiAudience;
    @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}")
    private String issuer;

    @Bean
    ForwardedHeaderFilter forwardedHeaderFilter() {
        return new ForwardedHeaderFilter();
    }

    @Bean
    JwtDecoder jwtDecoder() {
        NimbusJwtDecoder jwtDecoder = JwtDecoders.fromOidcIssuerLocation(issuer);

        OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(apiAudience);
        OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuer);
        OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);

        jwtDecoder.setJwtValidator(withAudience);

        return jwtDecoder;
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList(
                "http://localhost:4200"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE"));
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(Arrays.asList(
                "x-requested-with",
                "content-type",
                "Accept",
                "Authorization",
                "sentry-trace",
                "baggage"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);

        return source;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {

        String[] companiesEndpoints = {"/companies", "/companies/*"};
        String[] ideationEndpoint = {"/ideation", "/ideation/*"};
        String[] assessmentsEndpoints = {"/assessment", "/assessment/*", "/assessment/*/value-rating", "/assessment/*/viability-rating", "/assessment/*/customer-rating"};
        String[] teamsEndpoints = {"/teams", "/teams/*"};
        String[] userEndpoints = {"/users", "/users/*"};
        String[] projectEndpoints = {"/project", "/project/*", "/project-and-assessment"};
        String[] workspaceEndpoints = {"/workspace", "/workspace/*"};
        String[] tagEndpoints = {"/tag", "/tag/*"};


        http.authorizeHttpRequests((authorize) -> {
            try {
                authorize
                                .requestMatchers(companiesEndpoints).authenticated()
                                .requestMatchers(ideationEndpoint).authenticated()
                                .requestMatchers(assessmentsEndpoints).authenticated()
                                .requestMatchers(teamsEndpoints).authenticated()
                                .requestMatchers(userEndpoints).authenticated()
                                .requestMatchers(projectEndpoints).authenticated()
                                .requestMatchers(workspaceEndpoints).authenticated()
                                .requestMatchers(tagEndpoints).authenticated()
                                .requestMatchers(EndpointRequest.to("info")).hasAuthority("SCOPE_read:status")
                                .requestMatchers(EndpointRequest.to("health")).permitAll()
                                .and()
                                .oauth2ResourceServer((oauth2ResourceServer) ->
                                        oauth2ResourceServer.jwt(jwt -> jwt.decoder(jwtDecoder())));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });

        // Disable X-Frames on same origin to enable access to H2 in memory db console
        http.headers().frameOptions().sameOrigin();

        return http.build();
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 23:40:49