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

Keycloak与Spring Boot集成:请求OpenID配置时连接被拒

问题:Docker部署的Spring Boot应用无法连接同主机的Keycloak

环境配置

Keycloak Docker Compose 配置

keycloak:
    image: quay.io/keycloak/keycloak:20.0.1
    container_name: keycloak
    command:
      - start-dev
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.keycloak.rule=Host(`myhostname.com`) && PathPrefix(`/auth`)'
      - 'traefik.http.routers.keycloak.entrypoints=https'
      - 'traefik.http.routers.keycloak.tls=true'
      - 'traefik.http.routers.keycloak.tls.certresolver=letsencrypt'
    environment:
      KC_DB: mariadb
      KC_DB_URL: ${KC_DB_URL}
      KC_DB_USERNAME: ${MARIADB_USERNAME}
      KC_DB_PASSWORD: ${MARIADB_PASSWORD}
      KEYCLOAK_ADMIN: ${KEYCLOAK_SUPER_ADMIN_USER}
      KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_SUPER_ADMIN_PASS}
      KC_PROXY: ${KC_PROXY:-passthrough}
      KC_HTTP_RELATIVE_PATH: ${KC_HTTP_RELATIVE_PATH:-/auth}
    volumes:
      - ${PWD}/docker/keycloak:/opt/keycloak/data/import
    ports:
      - ${KEYCLOAK_PORT:-8087}:8080
    depends_on:
      - db-keycloak
    networks:
      net:

Keycloak通过Traefik反向代理暴露在https://myhostname.com/auth路径下。

Spring Boot应用Docker Compose配置

app:
    container_name: app
    image: ghcr.io/repo/image:tag
    environment:
      MARIADB_HOST: ${MARIADB_HOST}
      MARIADB_PORT: ${MARIADB_PORT}
      MARIADB_DATABASE: ${MARIADB_DATABASE}
      MARIADB_USERNAME: ${MARIADB_USERNAME}
      MARIADB_PASSWORD: ${MARIADB_PASSWORD}
      KEYCLOAK_CLIENT_ID: ${KEYCLOAK_CLIENT_ID}
      KC_HOSTNAME_URL: ${KC_HOSTNAME_URL}
      KEYCLOAK_REALM_NAME: ${KEYCLOAK_REALM_NAME}
    ports:
      - ${APP_PORT}:8080
    restart: always
    labels:
      - 'traefik.enable=true'
      - 'traefik.http.routers.app.rule=Host(`myhostname.com`) && PathPrefix(`/app`)'
      - 'traefik.http.routers.app.entrypoints=https'
      - 'traefik.http.routers.app.tls=true'
      - 'traefik.http.routers.app.tls.certresolver=letsencrypt'
    depends_on:
      - db
    networks:
      - net

Spring Boot应用通过Traefik暴露在https://myhostname.com/app路径下。

错误信息

应用启动时连接Keycloak失败,报错:

Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://myhostname.com/auth/realms/realm/.well-known/openid-configuration": Connection refused

Spring Boot配置文件

application.yaml

spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: ${KEYCLOAK_CLIENT_ID}
            scope: openid
            authorization-grant-type: authorization_code
        provider:
          keycloak:
            issuer-uri: ${KC_HOSTNAME_URL}/realms/${KEYCLOAK_REALM_NAME}
            user-name-attribute: preferred_username
      resourceserver:
        jwt:
          issuer-uri: ${KC_HOSTNAME_URL}/realms/${KEYCLOAK_REALM_NAME}

SecurityConfig.java

@Configuration
@EnableWebSecurity
class SecurityConfig {
  public static final String USER = "user";
  private final KeycloakLogoutHandler keycloakLogoutHandler;

  SecurityConfig(KeycloakLogoutHandler keycloakLogoutHandler) {
    this.keycloakLogoutHandler = keycloakLogoutHandler;
  }

  @Bean
  protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
    return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
  }

  @Bean
  public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.authorizeHttpRequests()
      .anyRequest().authenticated();
    http.oauth2Login()
      .and()
      .logout()
      .addLogoutHandler(keycloakLogoutHandler)
      .logoutSuccessUrl("/");
    http.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
    return http.build();
  }
}

已尝试的方案

  • 设置Keycloak客户端的Web Origins: *,无效
  • 将KC_HOSTNAME_URL设置为http://keycloak:8080/auth,应用能连接Keycloak,但前端授权功能无法正常工作

解决方案

1. 区分内部/外部访问地址

容器间通信使用内部地址,前端跳转使用外部地址,避免连接拒绝问题:

  • 修改Spring Boot的Docker Compose环境变量:
environment:
  KEYCLOAK_INTERNAL_URL: http://keycloak:8080/auth
  KEYCLOAK_EXTERNAL_URL: https://myhostname.com/auth
  • 更新application.yaml,分别配置客户端和资源服务器:
spring:
  security:
    oauth2:
      client:
        registration:
          keycloak:
            client-id: ${KEYCLOAK_CLIENT_ID}
            scope: openid
            authorization-grant-type: authorization_code
            provider: keycloak-external
        provider:
          keycloak-external:
            issuer-uri: ${KEYCLOAK_EXTERNAL_URL}/realms/${KEYCLOAK_REALM_NAME}
            user-name-attribute: preferred_username
          keycloak-internal:
            issuer-uri: ${KEYCLOAK_INTERNAL_URL}/realms/${KEYCLOAK_REALM_NAME}
            user-name-attribute: preferred_username
      resourceserver:
        jwt:
          issuer-uri: ${KEYCLOAK_INTERNAL_URL}/realms/${KEYCLOAK_REALM_NAME}

2. 修正Keycloak外部地址配置

Keycloak需要明确自身的外部访问地址,否则生成的授权链接会异常:

environment:
  KC_HOSTNAME: myhostname.com
  KC_HOSTNAME_PATH: /auth
  KC_HOSTNAME_STRICT_BACKCHANNEL: false
  • KC_HOSTNAME:设置为外部访问域名
  • KC_HOSTNAME_PATH:对应Traefik代理的路径
  • KC_HOSTNAME_STRICT_BACKCHANNEL:允许内部使用非外部地址访问

3. 验证Docker网络连通性

确认Traefik、Keycloak、Spring Boot应用都在同一个net网络中,进入Spring Boot容器执行以下命令测试连通性:

curl http://keycloak:8080/auth/realms/realm/.well-known/openid-configuration

4. 调整Traefik网络配置

如果Traefik未加入net网络,需要将其添加到该网络中;或者在Spring Boot容器的extra_hosts中添加域名映射:

extra_hosts:
  - "myhostname.com:traefik容器IP"

内容的提问来源于stack exchange,提问作者Spyros Mouchlianitis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 17:10:22