如何在应用层判断Keycloak用户是否通过X509证书登录?
解决Keycloak 16.1.1中脚本映射器无法获取ssl-client-cert请求头的问题
以下是针对该问题的排查和解决步骤:
1. 确认Nginx配置正确传递客户端证书头
要让Keycloak拿到客户端证书,首先得确保Nginx在反向代理时正确提取并传递证书:
- 配置Nginx的SSL验证和请求头传递:
server { listen 443 ssl; ssl_certificate /path/to/server.crt; ssl_certificate_key /path/to/server.key; ssl_client_certificate /path/to/ca.crt; ssl_verify_client optional; # 根据业务需求设为on/optional location /auth { proxy_pass http://your-keycloak-host:8080/auth; 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 $scheme; # 使用URL编码后的证书,避免换行符导致的头解析问题 proxy_set_header ssl-client-cert $ssl_client_escaped_cert; } } - 注意:必须使用
$ssl_client_escaped_cert而非$ssl_client_cert,后者的换行符会导致请求头无法被正确解析。
2. 配置Keycloak信任代理请求头
Keycloak默认可能会过滤未知请求头,需修改配置确保信任代理传递的头:
- 编辑
standalone.xml(或domain.xml)中的Undertow子系统配置:<subsystem xmlns="urn:jboss:domain:undertow:12.0"> <server name="default-server"> <http-listener name="default" socket-binding="http" redirect-socket="https" enable-http2="true" proxy-address-forwarding="true"/> <host name="default-host" alias="localhost"> <filter-ref name="x-forwarded-for"/> <filter-ref name="x-forwarded-proto"/> <filter-ref name="x-forwarded-host"/> <filter-ref name="x-forwarded-port"/> </host> </server> </subsystem> - 确保
proxy-address-forwarding="true"开启,该配置会让Keycloak信任代理传递的头信息。
3. 调整脚本映射器获取请求头的方式
原脚本可能因上下文问题无法获取头,尝试通过底层HttpServletRequest获取:
// 从HttpServletRequest实例中直接获取请求头 var request = keycloakSession.getContext().getHttpRequest().getHttpServletRequest(); var nginxCertHeader = request.getHeader("ssl-client-cert"); token.getOtherClaims().put("client-cert", nginxCertHeader);
Keycloak 16.1.1中,部分场景下getRequestHeaders()无法直接读取自定义头,通过getHttpServletRequest()获取更可靠。
4. 验证请求头是否到达Keycloak
启用调试日志确认头是否被正确接收:
- 在
standalone.xml中添加日志配置:<logger category="org.keycloak.services"> <level name="DEBUG"/> </logger> - 重启Keycloak后,查看日志中是否有包含
ssl-client-cert的请求记录,以此确认头是否成功传递。
内容的提问来源于stack exchange,提问作者Rodrigo Lira
相关产品推荐
相关产品推荐

