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自动配置,手动定义ReactiveJwtDecoderBean,自定义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
相关产品推荐
相关产品推荐

