我有一个配置为反向代理的 Apache 2.4 服务器,用于接受传入的 HTTPS 请求并通过 HTTP 将它们反向代理到另一台服务器,并使用包含任何提供的客户端证书信息的自定义 HTTP 标头。
我的配置的简化版本:
<VirtualHost _default_:443>
SSLCertificateFile "/path/to/server.crt"
SSLCertificateKeyFile "/path/to/server.key"
SSLCACertificateFile "/path/to/client-ca-chain.pem"
SSLVerifyClient optional
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://remote-server/
ProxyPassReverse / http://remote-server/
RequestHeader add X-Forwarded-Proto https
RequestHeader add X-Forwarded-Port 443
RequestHeader set Client-Cert-Subject "%{SSL_CLIENT_S_DN}s"
</VirtualHost>
在大多数情况下,这是没问题的,但是事情变得有点奇怪,因为证书认证是可选的。
当用户提供他们的证书时,远程系统会看到Client-Cert-Subject
如我预期的标头:
Client-Cert-Subject: CN=USER.NAME.0123456789,OU=BLAH,O=WHATEVER,C=STUFF
当用户不提供其证书时(例如,在浏览器提示时单击“取消”而不是其证书),标头仍然包含在内,但包含文本字符串(null)
:
Client-Cert-Subject: (null)
这让远程服务器非常生气。
我想做的是,%{SSL_CLIENT_S_DN}s
当用户提供证书时,包含使用 检索到的证书主题的标头,但如果用户未提供证书,则根本不包含标头。如果在没有证书信息时将标头作为空字符串提供,这也是可以接受的,尽管很奇怪?
我尝试过多次使用If
指令,例如
<If "-n %{SSL_CLIENT_S_DN}s">
RequestHeader set Client-Cert-Subject "%{SSL_CLIENT_S_DN}s"
</If>
并在 RequestHeader 指令上使用表达式,例如
RequestHeader set Client-Cert-Subject "%{SSL_CLIENT_S_DN}s" expr="-n %{SSL_CLIENT_S_DN}s"
但总是出现语法错误、总是出现标题或从不出现标题。
Client-Cert-Subject
当实际存在客户端证书时,如何强制 apache 有条件地包含我?
答案1
例如标头表达式表明整个参数必须用引号引起来(“expr=...”而不是 expr="...”)。我最终得到了
RequestHeader set X-SSL-CLIENT-CERT "%{SSL_CLIENT_CERT}s" "expr=-n %{SSL_CLIENT_CERT}"
并且这有效,“null”字符串不再出现(Apache 2.4.6)。