Spring Boot微服务Spring Security OIDC/OAuth2代理下Issuer不匹配求助
解决Spring Security JWT Issuer不匹配问题
你的问题核心是网关/代理导致客户端访问的授权服务器地址与令牌中的issuer不一致,Spring Security默认会严格校验issuer的匹配性,因此抛出异常。以下是几种可行的解决方案:
方案1:配置Issuer映射(Spring Boot 2.6+ 推荐)
如果使用Spring Boot 2.6及以上版本,可以直接通过配置文件将实际返回的issuer映射为客户端配置的地址,无需修改代码:
在application.yml中添加:
spring: security: oauth2: resourceserver: jwt: issuer-uri: https://clidens1.aqp.it:9443/oauth2/token issuer-mapping: https://ids-for-spid.aqp.it/oauth2/token: https://clidens1.aqp.it:9443/oauth2/token
该配置会让Spring Security将令牌中的https://ids-for-spid.aqp.it/oauth2/token视为与配置的issuer等价,直接通过校验。
方案2:自定义JWT解码器(适配旧版本)
对于Spring Boot 2.6以下版本,或者需要更灵活的校验逻辑,可以自定义JwtDecoder来处理issuer的匹配:
@Configuration @EnableWebSecurity public class SecurityConfig { @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}") private String configuredIssuer; @Bean public JwtDecoder jwtDecoder() { // 基于配置的issuer创建默认解码器 NimbusJwtDecoder decoder = NimbusJwtDecoder.withJwkSetUri(configuredIssuer + "/.well-known/jwks.json").build(); // 替换默认的JWT校验逻辑,处理issuer映射 decoder.setJwtValidator(jwt -> { String tokenIssuer = jwt.getIssuer(); // 匹配实际返回的issuer,替换为配置的地址 if ("https://ids-for-spid.aqp.it/oauth2/token".equals(tokenIssuer)) { // 构造新的JWT对象,将issuer替换为配置值 Jwt adjustedJwt = Jwt.withTokenValue(jwt.getTokenValue()) .headers(jwt.getHeaders()) .claims(claims -> claims.putAll(jwt.getClaims())) .issuer(configuredIssuer) .build(); // 返回校验通过的结果 return JwtValidatorResult.success(adjustedJwt); } // 其他情况沿用默认校验逻辑 return JwtValidatorResult.success(); }); return decoder; } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt -> jwt.decoder(jwtDecoder()))); return http.build(); } }
方案3:修改授权服务器的Issuer配置(根源解决)
如果有权限修改授权服务器(如Spring Authorization Server、Keycloak等),直接将授权服务器的issuer配置为代理后的访问地址https://clidens1.aqp.it:9443/oauth2/token,这样well-known配置返回的issuer会与客户端访问地址完全一致,从根源避免该问题。
以Spring Authorization Server为例,配置ProviderSettings:
@Bean public ProviderSettings providerSettings() { return ProviderSettings.builder() .issuer("https://clidens1.aqp.it:9443/oauth2/token") .build(); }
内容的提问来源于stack exchange,提问作者Danilo Giovannico
相关产品推荐
相关产品推荐

