我正在尝试使用 Docker 配置 Keycloak。 Keycloak 用于 Angular 前端应用程序以及 java spring 后端应用程序中的身份验证。 我对这些服务的 docker-compose 配置如下:
backend:
image: backend
container_name: backend
build:
context: ./backend
ports:
- 8080:8081
depends_on:
- db
networks:
- net
restart: always
frontend:
image: frontend
container_name: frontend
build:
context: ./frontend
ports:
- 80:80
depends_on:
- backend
networks:
- net
restart: always
keycloak:
image: quay.io/keycloak/keycloak:25.0.4
command: start
environment:
KC_HOSTNAME_PORT: 8080
KC_HTTP_ENABLED: true
KC_HOSTNAME_STRICT_HTTPS: false
KC_HEALTH_ENABLED: true
KEYCLOAK_ADMIN: ${KEYCLOAK_ADMIN_USER}
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PWD}
KC_DB: postgres
KC_DB_URL: ${KEYCLOAK_DB_URL}
KC_DB_USERNAME: ${KEYCLOAK_DB_USERNAME}
KC_DB_PASSWORD: ${KEYCLOAK_DB_PWD}
KC_HOSTNAME_STRICT: false
KC_PROXY: edge
KC_HOSTNAME: http://keycloak:8080
KC_HOSTNAME_BACKCHANNEL_DYNAMIC: true
ports:
- 8083:8080
restart: always
networks:
- net
db:
image: 'postgres'
container_name: db
environment:
- POSTGRES_USER=${POSTGRES_USER}
- POSTGRES_PASSWORD=${POSTGRES_PWD}
ports:
- "5432:5432"
networks:
- net
spring的属性是这样的:
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://keycloak:8080/realms/<realm-name>
在角度中,我使用以下配置:
config: {
url: 'http://localhost:8083',
realm: "<realm-name>",
clientId: "<client-id>"
}
后端的身份验证工作正常,但问题是前端应用程序中的身份验证,因为 keycloak 主机名是“keycloak”,在前端应用程序中它不知道该主机名。如果我将其更改为 localhost,则后端容器无法连接到 keycloak 容器。
有谁知道我该如何解决这个问题?
Spring 的
issuer-uri
属性应使用 OIDC 规范中定义的 Issuer Identifier 进行设置。
由于OIDC发现和OpenID令牌验证规范,这个发行者标识符必须与中的完全相同
相同{Issuer Identifier}/.well-known/openid-configuration
issuer
属性(在发现端点公开)iss
声明和内省端点对于 Keycloak,这些值取决于
hostname
和 hostname-strict
属性。您应该 使用 hostname
一个在 Docker 和运行您用来显示 SPA 的浏览器的主机中已知的值。 由于您似乎正在使用反向代理 (edge
),我会使用通过该反向代理的 URI(注意主机名,还有方案和端口),以及 hostname-strict=true
以确保所有内容仅使用该 URI。
keycloak
仅在 Docker 内已知,这是因为 http://keycloak:8080
适用于 Spring 容器,但不适用于 Docker 主机上的浏览器。 loclahost
在浏览器中工作,因为您在主机上公开了 Keycloak,但从 Spring 容器中,localhost
循环到自身,而不是主机。
在我写的这篇文章中,介绍了 Keycloak 与 Spring,我使用了主机上 hostname
命令的值(或
$HOSTNAME
环境变量)。附注
另一篇文章。请注意,此 OAuth2 BFF 模式仍然使用授权代码流。因此,这并不能消除浏览器重定向到授权服务器的需要 - 并且授权服务器主机名可以从所有涉及的主机和容器中解析。