SSLUserName仅支持绑定预定义变量如SSL_CLIENT_S_DN_UID,需配合SSLVerifyClient require、SSLRequireSSL及SSLOptions +StdEnvVars启用;证书必须含UID字段,且后端需正确解码URL编码值。
要通过虚拟主机配置
指令将证书中的
字段导出至后端应用系统,关键不是“导出”动作本身,而是让 apache 正确提取并注入该字段为环境变量(如
),再由后端(如 php、python wsgi、cgi 等)读取使用。整个过程依赖严格的前提条件和精确的配置顺序。
必须启用双向认证与环境变量透传
SSLUserName 不会自动生效,它只在客户端证书验证成功后才起作用:
强制客户端提供证书
:在
块中必须设置
;仅设
或不设,
全为空
限定 HTTPS 访问
:添加
(或确保该站点仅监听 443 且无 HTTP 回退)
透传变量给后端
:Apache 2.4+ 需在对应
或
中加入
,否则 PHP 的
或 CGI 环境里看不到
确认证书实际包含 UID 字段
SSLUserName 只能绑定已解析出的字段,而
是否可用,取决于客户端证书是否在
中嵌入了
:
公网 CA(如 Let’s Encrypt、DigiCert)签发的证书通常不含
,该字段多见于企业私有 CA 或 LDAP 集成场景
可用命令快速验证:
若输出为空,说明证书没带 UID,
恒为空字符串,后续绑定无效
在 VirtualHost 中正确配置 SSLUserName
语法极简,但容错率低,不能拼接、不能正则、不能空格处理:
直接写:
(推荐,最稳妥)
不要写:
(语法错误,mod_
ssl
不支持变量插值)
注意编码:UID 值若含空格或特殊字符,会被自动 URL 编码(如
→
),后端需调用
或等效函数解码后再使用
后端应用如何获取该值
配置生效后,该值作为 CGI 环境变量暴露,不同后端读取方式不同:
PHP
:可通过
获取(需开启
)
Python WSGI
:在
字典中查找键
Node.js(HTTP 模块)
:需 Apache 用
转发时显式设置请求头,例如:
,再由 Node.js 读
头
sslusernameuidssl_client_s_dn_uidSSLVerifyClient requireoptionalSSL_CLIENT_S_DN_*SSLRequireSSLSSLOptions +StdEnvVars$_SERVERSSL_CLIENT_S_DN_UIDSSL_CLIENT_S_DN_UIDSubjectUID=xxxUIDopenssl x509 -in client.crt -text -noout | grep -i "uid"SSL_CLIENT_S_DN_UIDSSLUserName SSL_CLIENT_S_DN_UIDSSLUserName "UID=${SSL_CLIENT_S_DN_UID}"user nameuser+nameurldecode()$_SERVER['SSL_CLIENT_S_DN_UID']SSLOptions +StdEnvVarsenvironSSL_CLIENT_S_DN_UIDmod_proxyRequestHeader set X-Client-UID "%{SSL_CLIENT_S_DN_UID}e"X-Client-UID