Spring Security Issuer URI是否支持通过Eureka服务发现使用服务名?
你的结论部分正确:直接将Eureka服务名作为Spring Security OAuth2资源服务器的issuer-uri确实无法正常工作,但不是完全不能用服务发现机制对接,只是你的使用方式不符合Spring Security的默认行为规范。
为什么会出现UnknownHostException
Spring Security OAuth2资源服务器在配置issuer-uri后,会自动发起请求获取授权服务器的OIDC元数据(如/.well-known/openid-configuration)和JWKS密钥集。这个请求默认使用JDK原生HTTP客户端,该客户端仅依赖系统DNS解析域名,不会集成Eureka的服务发现逻辑,因此无法将authorization-server这个服务名解析为对应服务实例的IP,最终抛出域名解析失败的异常。
正确的对接方式
要让资源服务器通过Eureka服务发现对接授权服务器,需要自定义JwtDecoder,手动结合服务发现机制获取授权服务器的真实地址,而非直接依赖issuer-uri的自动配置。
方案1:结合Spring Cloud LoadBalancer自定义JwtDecoder
如果你的项目已引入Spring Cloud组件,可利用Spring Cloud LoadBalancer实现服务发现:
- 确保项目中包含Spring Cloud LoadBalancer依赖(通常Spring Cloud Starter已集成)
- 自定义
JwtDecoderBean,通过服务发现获取授权服务器实例地址,再构建JWKS URI:
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient; import org.springframework.security.oauth2.jwt.JwtDecoder; import org.springframework.security.oauth2.jwt.NimbusJwtDecoder; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class JwtConfig { @Bean public JwtDecoder jwtDecoder(LoadBalancerClient loadBalancerClient) { // 通过服务发现选择授权服务器实例 ServiceInstance authServerInstance = loadBalancerClient.choose("authorization-server"); // 拼接JWKS端点地址(根据授权服务器实际端点调整) String jwksUri = authServerInstance.getUri() + "/.well-known/jwks.json"; return NimbusJwtDecoder.withJwkSetUri(jwksUri).build(); } }
同时需要移除原配置中的spring.security.oauth2.resourceserver.jwt.issuer-uri,避免自动配置的JwtDecoder覆盖自定义Bean。
方案2:确保JWT的issuer声明为可解析地址
另外需注意:JWT中的iss(issuer)声明必须和资源服务器校验时使用的issuer严格一致。如果授权服务器签发JWT时用服务名authorization-server作为issuer,即使资源服务器能通过服务发现获取到地址,JWT校验也会因issuer不匹配失败。因此建议:
- 授权服务器配置签发JWT时,使用可公开解析的域名(或内部DNS可解析的地址)作为issuer
- 资源服务器的
issuer-uri配置为该真实地址,若需通过服务发现调用授权服务器其他接口,单独使用服务名进行调用
内容的提问来源于stack exchange,提问作者Katlock

