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

如何在应用层判断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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 14:05:23