Docker部署Spring Authorization Server后请求返回401错误
Docker部署后OAuth2资源服务器返回401未授权错误
环境信息
- Spring Boot 3.0.4
- spring-security-oauth2-authorization-server 1.0.2
- spring-boot-starter-oauth2-resource-server
- 已集成自定义授权授予类型
- 本地测试授权流程正常,Docker化部署后请求返回HTTP 401响应码
复现步骤
- 通过Docker Compose部署包含Eureka注册中心、网关、授权服务器(auth)、资源服务器(news)的微服务集群
- 资源服务器配置Docker环境下的
issuer-uri指向容器内授权服务器地址 - 调用资源服务器API,返回401未授权响应
相关配置代码
资源服务器application-docker.yaml配置
spring: security: oauth2: resourceserver: jwt: issuer-uri: http://auth:8092
Docker Compose配置(docker-compose.yaml)
version: '3' services: eureka-server: image: xxxxxxx container_name: eureka-server ports: - "8761:8761" environment: - SPRING_PROFILES_ACTIVE=docker networks: - spring apigw: image: xxxxxxx container_name: apigw ports: - "8080:8080" environment: - SPRING_PROFILES_ACTIVE=docker networks: - spring depends_on: - eureka-server auth: image: xxxxxxx container_name: auth ports: - "8092:8092" environment: - SPRING_PROFILES_ACTIVE=docker networks: - spring - postgres depends_on: - postgres - eureka-server news: # 这是资源服务器 image: xxxxxxx container_name: news ports: - "8083:8083" environment: - SPRING_PROFILES_ACTIVE=docker networks: - spring - postgres depends_on: - postgres - eureka-server - auth networks: spring: driver: bridge
资源服务器SecurityConfig配置(修正乱码后)
@Configuration //@Order(1) public class SecurityConfig { @Value("${spring.security.oauth2.resourceserver.jwt.issuer-uri}") private String issuerUri; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeHttpRequests() .requestMatchers("/api/news/pre-authentication").anonymous() .anyRequest().permitAll() .and() .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt); return http.build(); } @Bean public JwtDecoder jwtDecoder() { return JwtDecoders.fromIssuerLocation(issuerUri); } }
核心问题
本地测试时授权流程完全正常,但Docker部署后,调用资源服务器API始终返回401未授权响应,期望请求能正常通过授权验证。
可能的原因及解决方法
1. 授权服务器Issuer配置不匹配
Docker环境下资源服务器配置的issuer-uri是容器内部地址http://auth:8092,但授权服务器自身配置的Issuer可能还是本地地址(如http://localhost:8092)。JWT的iss声明必须与资源服务器的issuer-uri完全一致,否则会验证失败。
解决方法:
在授权服务器的Docker环境配置中,将Issuer设置为容器内部地址:
# 授权服务器application-docker.yaml spring: security: oauth2: authorization-server: issuer: http://auth:8092
2. 资源服务器无法访问授权服务器JWKS端点
资源服务器通过issuer-uri自动发现JWKS端点(通常为http://auth:8092/oauth2/jwks),若网络不通或授权服务器未暴露该端点,会导致JWT解码失败。
解决方法:
- 确认资源服务器与授权服务器在同一Docker网络(已在docker-compose中配置
spring网络) - 进入资源服务器容器执行
curl http://auth:8092/oauth2/jwks,检查是否能正常返回JWKS内容 - 确保授权服务器的Security配置允许匿名访问JWKS端点
3. JWT受众(Audience)验证失败
若授权服务器颁发的JWT中aud声明不包含资源服务器的Client ID,资源服务器会拒绝该Token。
解决方法:
- 在授权服务器配置中,为资源服务器对应的Client配置正确的受众或权限范围
- 资源服务器可显式配置允许的受众:
# 资源服务器application-docker.yaml spring: security: oauth2: resourceserver: jwt: issuer-uri: http://auth:8092 audiences: news-service # 替换为资源服务器实际Client ID
4. 容器启动顺序导致JWKS初始化失败
虽然docker-compose配置了depends_on,但授权服务器可能未完全启动时资源服务器已初始化JwtDecoder,导致无法获取JWKS且后续未自动刷新。
解决方法:
- 为资源服务器添加启动延迟,或使用健康检查机制确保授权服务器就绪后再启动资源服务器
- 配置JwtDecoder支持JWKS缓存与自动刷新:
@Bean public JwtDecoder jwtDecoder() { NimbusJwtDecoder jwtDecoder = JwtDecoders.fromIssuerLocation(issuerUri); // 设置JWKS缓存刷新间隔为5分钟 jwtDecoder.setJwkSetCache(new DefaultJWKSetCache(Duration.ofMinutes(5))); return jwtDecoder; }
内容的提问来源于stack exchange,提问作者Jethro
相关产品推荐
相关产品推荐

