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

Spring Security issuer-uri被自动追加尾斜杠如何解决

问题根因

你看到的issuer末尾斜杠不是Spring Security自动追加的:

  • Spring Security配置issuer-uri后,会默认请求{issuer-uri}/.well-known/openid-configuration拉取OIDC授权服务器元数据
  • 拉取到元数据后会做严格字符串相等校验,要求本地配置的issuer-uri和元数据返回的issuer字段完全一致,差一个字符(包括末尾斜杠)就会抛出你遇到的IllegalStateException
  • 元数据里的末尾斜杠要么是授权服务器的发现端点本身返回的issuer字段带斜杠(属于授权服务器OIDC实现不规范,和自身文档要求矛盾),要么是请求发现端点时被服务端3xx重定向补了根路径斜杠,导致返回的元数据issuer对应带斜杠。
解决方案

按落地成本从低到高排序:

方案1:关闭OIDC自动发现,全量手动配置端点(最稳妥)

你已经手动配置了authorization-uri、token-uri,完全不需要Spring自动拉取远程元数据,做三处修改即可:

  • 删掉application.yaml中spring.security.oauth2.client.provider.IdOfProvider下的issuer-uri配置,补充配置jwk-set-uri(一般为https://api.provider.guys.com/.well-known/jwks.json,按服务端实际文档填写)
  • 修改手动构建ClientRegistration的代码,删掉.issuerUri(issuerUri)这行调用,避免触发自动元数据拉取逻辑
  • 资源服务器JWT校验部分不要用默认的issuer-uri自动配置,手动定义ReactiveJwtDecoder Bean,自定义issuer校验逻辑,归一化斜杠后再比对:
@Bean
public ReactiveJwtDecoder jwtDecoder() {
    NimbusReactiveJwtDecoder decoder = NimbusReactiveJwtDecoder
            .withJwkSetUri("https://api.provider.guys.com/.well-known/jwks.json")
            .build();
    OAuth2TokenValidator<Jwt> issuerValidator = token -> {
        String rawIssuer = token.getIssuer().toString();
        final String EXPECTED_ISSUER = "https://api.provider.guys.com";
        // 统一移除末尾斜杠后做比对
        String normalizedIssuer = rawIssuer.endsWith("/") 
                ? rawIssuer.substring(0, rawIssuer.length() - 1) 
                : rawIssuer;
        return normalizedIssuer.equals(EXPECTED_ISSUER)
                ? OAuth2TokenValidatorResult.success()
                : OAuth2TokenValidatorResult.failure(
                        new OAuth2Error("invalid_token", "Issuer not match", null)
                );
    };
    decoder.setJwtValidator(issuerValidator);
    return decoder;
}

方案2:自定义OIDC元数据解析器,自动修正返回的issuer值

如果需要保留OIDC自动发现能力,直接替换默认的元数据解析器,在解析元数据时自动移除issuer末尾的斜杠:

@Bean
public ReactiveOidcProviderConfigurationResolver oidcProviderConfigurationResolver() {
    WebClientReactiveOidcProviderConfigurationResolver resolver =
            new WebClientReactiveOidcProviderConfigurationResolver();
    WebClient webClient = WebClient.builder()
            .filter((request, next) -> next.exchange(request)
                    .flatMap(response -> response.bodyToMono(Map.class)
                            .map(metadata -> {
                                String issuer = (String) metadata.get("issuer");
                                if (issuer != null && issuer.endsWith("/")) {
                                    metadata.put("issuer", issuer.substring(0, issuer.length() - 1));
                                }
                                return metadata;
                            })
                            .flatMap(modifiedMetadata -> ServerResponse.from(response)
                                    .body(BodyInserters.fromValue(modifiedMetadata))
                                    .build())))
            .build();
    resolver.setWebClient(webClient);
    return resolver;
}

注意:不要直接把本地配置的issuer-uri改成带末尾斜杠的值,API提供方明确要求请求中issuer不得携带末尾斜杠,修改本地配置会导致后续接口请求被服务端拒绝。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:39:21