sslusername 本身不导出证书 uid,而是将 ssl_client_s_dn_uid 等预定义变量绑定为认证用户标识;需确保客户端证书含 uid 字段、启用 sslverifyclient require、ssloptions +stdenvvars,并在 https 虚拟主机内配置。

SSLUserName 本身不导出证书 UID,它只是把一个固定值或预定义变量(比如 SSL_CLIENT_S_DN_UID)绑定为 Apache 认证用户标识。要让 SSLUserName SSL_CLIENT_S_DN_UID 生效,关键不是“导出 UID”,而是确保该变量有值、能被正确读取,并在后续流程中可用。
以下是你实际需要做的几件事:
确认客户端证书里真有 UID 字段
SSL_CLIENT_S_DN_UID 只在证书的 Distinguished Name 中明确包含 UID= 属性时才非空。公网 CA(如 Let’s Encrypt、DigiCert)几乎从不写 UID;它常见于企业私有 PKI 或 LDAP 集成场景。生成 CSR 时需显式添加:
openssl req -new -key client.key -subj "/C=CN/ST=Beijing/L=Beijing/O=MyOrg/UID=john.doe" -out client.csr
否则 SSL_CLIENT_S_DN_UID 永远为空,SSLUserName 绑定的也是空字符串。
启用必要指令并限定作用域
SSLUserName 必须配合强制认证和 HTTPS 环境使用:
- 在
<virtualhost></virtualhost>或<directory></directory>块内配置,不能放全局; - 必须设置
SSLVerifyClient require,否则客户端不发证书,所有 SSL_* 变量为空; - 必须开启
SSLRequireSSL(通常默认已开),防止降级到 HTTP; - 若后端是 PHP/CGI,还需加
SSLOptions +StdEnvVars,否则环境变量不透传。
示例片段:
<virtualhost>
SSLEngine on
SSLCertificateFile /etc/ssl/cert/server.crt
SSLCertificateKeyFile /etc/ssl/cert/server.key
SSLCACertificateFile /etc/ssl/cert/ca.crt
SSLVerifyClient require
SSLVerifyDepth 2
SSLUserName SSL_CLIENT_S_DN_UID
SSLOptions +StdEnvVars
<directory>
Require valid-user
</directory></virtualhost>
验证 UID 是否真正可用
部署后,用支持客户端证书的工具测试(浏览器需手动选证书,curl 更可靠):
curl -k --cert client.crt --key client.key https://your-server/whoami.php
在 whoami.php 中打印:
<?php echo $_SERVER['SSL_CLIENT_S_DN_UID'] ?? 'MISSING'; ?>
若输出为空,说明证书没 UID、CA 链不对、或 SSLVerifyClient 没生效。
注意几个硬性限制
- Apache 2.4.8+ 才支持 SSLUserName,旧版直接忽略;
-
SSL_CLIENT_S_DN_UID值会自动 URL 编码(如空格变+,@变%40),后端应用需解码才能用于查询; - 不支持正则提取或拼接,例如
SSLUserName "uid-${SSL_CLIENT_S_DN_UID}"是非法语法; - SELinux 或文件权限问题可能导致私钥或 CA 证书读取失败,进而使整个验证链中断。
不复杂但容易忽略。











