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

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响应码

复现步骤

  1. 通过Docker Compose部署包含Eureka注册中心、网关、授权服务器(auth)、资源服务器(news)的微服务集群
  2. 资源服务器配置Docker环境下的issuer-uri指向容器内授权服务器地址
  3. 调用资源服务器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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 07:19:53