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

Docker Compose下SpringBoot对接Keycloak颁发者不匹配问题排查

SpringBoot + Keycloak Docker Compose部署时Issuer不匹配问题解决

问题现象

启动服务时抛出以下错误:

Caused by: java.lang.IllegalStateException: The Issuer "http://localhost:8080/realms/RepitRealm" provided in the configuration metadata did not match the requested issuer "http://keycloak:8080/realms/RepitRealm"

相关配置

1. docker-compose.yml关键片段

networks:
  local-keycloak:

services:
  keycloak:
    build: ./keycloak/
    container_name: repit-keycloak
    ports:
      - "8881:8080"
      - "8443:8443"
    volumes:
      - ./keycloak/data:/opt/keycloak/data/import
    environment:
      KEYCLOAK_ADMIN: "admin"
      KEYCLOAK_ADMIN_PASSWORD: "admin"
#      KC_HOSTNAME: "keycloak"
    networks:
      - local-keycloak
    depends_on:
      - keycloak-db
    restart: unless-stopped
    command:
      - start-dev
      - --import-realm

  backend:
    image: [...]
    container_name: repit-backend
    environment:
      spring_profiles_active: "external"
      KEYCLOAK_URL: "http://keycloak:8080/realms/RepitRealm"
      APPLICATION_PORT: "8880"
    ports:
      - "8880:8880"
    networks:
      - local-keycloak
    depends_on:
      - keycloak
    restart: unless-stopped

2. Keycloak Dockerfile内容

FROM quay.io/keycloak/keycloak:latest as builder

# Enable health and metrics support
ENV KC_HEALTH_ENABLED=true
ENV KC_METRICS_ENABLED=true

# Configure a database vendor
ENV KC_DB=postgres

WORKDIR /opt/keycloak
# for demonstration purposes only, please make sure to use proper certificates in production instead
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:localhost,IP:127.0.0.1" -keystore conf/server.keystore
RUN /opt/keycloak/bin/kc.sh build

FROM quay.io/keycloak/keycloak:latest
COPY --from=builder /opt/keycloak/ /opt/keycloak/

# change these values to point to a running postgres instance
ENV KC_DB=postgres
ENV KC_DB_URL=jdbc:postgresql://keycloak-db:5432/keycloak
ENV KC_DB_USERNAME=keycloak
ENV KC_DB_PASSWORD=password
ENV KC_HOSTNAME=localhost
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]

3. SpringBoot "external"配置文件关键片段

spring.security.oauth2.client.registration.keycloak.client-id=repit
spring.security.oauth2.client.registration.keycloak.authorization-grant-type=authorization_code
spring.security.oauth2.client.registration.keycloak.scope=openid
spring.security.oauth2.client.provider.keycloak.issuer-uri=${KEYCLOAK_URL}
spring.security.oauth2.client.provider.keycloak.user-name-attribute=preferred_username
spring.security.oauth2.resourceserver.jwt.issuer-uri=${KEYCLOAK_URL}

注:直接在IDE启动后端时运行正常;将Keycloak的KC_HOSTNAME改为keycloak后服务可启动,但前端认证会被重定向到http://keycloak:8881/realms/RepitRealm。

问题原因

核心矛盾在于Keycloak返回的Issuer地址和SpringBoot请求的地址不一致:

  • SpringBoot容器通过Docker内部服务名keycloak请求Keycloak,配置的Issuer是http://keycloak:8080/realms/RepitRealm
  • Keycloak因Dockerfile中KC_HOSTNAME=localhost的配置,返回的Issuer是http://localhost:8080/realms/RepitRealm
  • SpringBoot的OAuth2客户端会严格校验Issuer一致性,导致启动失败

解决方案

方案1:本地开发环境适配(同时支持容器内通信和外部浏览器访问)

该方案让Keycloak同时兼容内部服务名和外部localhost访问,解决容器通信和前端重定向问题:

  1. 修改docker-compose.yml中Keycloak的环境变量

    environment:
      KEYCLOAK_ADMIN: "admin"
      KEYCLOAK_ADMIN_PASSWORD: "admin"
      KC_HOSTNAME: localhost
      KC_HOSTNAME_STRICT: false
      KC_HOSTNAME_STRICT_HTTPS: false
      KC_HTTP_ENABLED: true
      KC_PROXY: edge
    
    • KC_HOSTNAME_STRICT: false:允许Keycloak接受不同主机名的请求
    • KC_PROXY: edge:让Keycloak从请求头中获取真实访问地址,适配端口映射场景
    • 保留KC_HOSTNAME=localhost确保前端访问时重定向地址正确
  2. 配置本地hosts映射
    在本地机器的hosts文件中添加:

    127.0.0.1 keycloak
    

    这样前端访问http://keycloak:8881/realms/RepitRealm会解析到本地,避免无法访问的问题

  3. 保持SpringBoot配置不变
    继续使用KEYCLOAK_URL: "http://keycloak:8080/realms/RepitRealm",容器内通过服务名通信性能最优

方案2:统一访问地址(适合测试/生产)

如果不需要同时支持两种访问方式,可统一用localhost作为访问入口:

  1. 修改SpringBoot的环境变量
    将KEYCLOAK_URL改为http://localhost:8080/realms/RepitRealm

  2. 确保Keycloak配置正确
    保持KC_HOSTNAME=localhost,容器端口映射8881:8080不变

  3. 容器访问宿主机适配
    若SpringBoot容器无法直接访问localhost,可替换为host.docker.internal(Docker内置的宿主机别名,Windows/macOS默认支持,Linux需额外配置)

验证方法

启动服务后,访问http://localhost:8881/realms/RepitRealm/.well-known/openid-configuration,查看返回的issuer字段是否与SpringBoot配置的一致。一致则说明配置正确。

内容的提问来源于stack exchange,提问作者Romain Hardenne

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 18:48:12