我想在 docker swarm 模式下在 nginx 反向代理后面的非根路径 ( /auth ) 中运行 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=mysql
WORKDIR /opt/keycloak
#Generating a Self-Signed Certificate
RUN keytool -genkeypair -storepass password -storetype PKCS12 -keyalg RSA -keysize 2048 -dname "CN=server" -alias server -ext "SAN:c=DNS:app.example.com" -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 Mysql instance
ENV KC_DB=mysql
ENV KC_DB_URL=jdbc:mysql://keycloak_database:3306/keycloak
ENV KC_DB_USERNAME=keycloak
ENV KC_DB_PASSWORD=keycloak
ENV KC_HOSTNAME_URL=https://app.example.com/auth/
ENV KC_HOSTNAME_ADMIN_URL=https://app.example.com/auth/
ENV KC_PROXY=edge
ENV KC_LOG_LEVEL=INFO
ENV KC_HOSTNAME_DEBUG=true
ENV KC_HOSTNAME_STRICT=false
ENTRYPOINT ["/opt/keycloak/bin/kc.sh"]
使用上面的 docker 文件,我使用此命令来运行 keycloak 服务,其中 keycloakpro 是图像名称
docker service create --name keycloak --network test_overlay --constraint node.labels.server==true --env KEYCLOAK_ADMIN=admin --env KEYCLOAK_ADMIN_PASSWORD=admin keycloakpro start --optimized
这是我的 nginx 反向代理配置,
server {
listen 443 ssl;
index index.html index.htm index.nginx-debian.html;
server_name app.example.com;
ssl_certificate /home/certificate.crt;
ssl_certificate_key /home/private.key;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
access_log /var/log/nginx/reverse-access.log;
error_log /var/log/nginx/reverse-error.log;
location /backend {
rewrite ^/backend(.*)$ $1 break;
proxy_pass http://backend-server:9999/;
proxy_redirect off;
}
location /auth {
rewrite ^/auth(.*)$ $1 break;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host app.example.com;
proxy_set_header X-Forwarded-Port 8443;
proxy_pass https://keycloak:8443/;
add_header Set-Cookie $http_cookie;
}
location / {
rewrite ^/(.*)$ /$1 break;
proxy_pass http://react-server/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection ‘upgrade’;
proxy_cache_bypass $http_upgrade;
}
}
server {
listen 80;
server_name app.example.com;
return 301 https://$host$request_uri;
}
在上面的 nginx 配置中,我有一个在“/backend”位置块中运行的后端服务,以及一个由 nginx 在根路径中提供服务的 React 服务器。
当以上所有配置一起使用时,将可以通过https://app.example.com/auth
访问keycloak当我访问 https://app.example.com/auth/ 时,它会将我重定向到 Keycloak 页面。此 URL 将我带到管理员页面:https://app.example.com/auth/admin/。
这将启动 OAuth2 流登录页面:https://app.example.com/auth/realms/master/protocol/openid-connect/auth?client_id=security-admin-console ...
一旦达到这一点,Keycloak 就会在浏览器中存储一个 cookie,但在我的情况下不会发生这种情况。如果我使用 https://app.example.com:8443/ 访问它,则会设置 cookie,并且我无法登录。只有当请求抛出代理时,它才不会设置 cookie。
我检查了与此相关的各种文章,但没有一篇能够解决我的问题。 如有任何帮助,我们将不胜感激。
实际上这是我的错误,我忽略了反向代理的 nginx.conf 文件中的 cookie 标头,因此出现了上述问题。 更具体地说,是因为这些线,
proxy_ignore_headers Expires Cache-Control Set-Cookie;
proxy_hide_header Set-Cookie;
注释掉这两行就成功了。