基于 SSL(客户端认证)的动态 DocumentRoot

基于 SSL(客户端认证)的动态 DocumentRoot

我目前使用客户端 SSL 身份验证来保护敏感内容。用户需要将我们使用 OpenSSL 生成的证书导入到他们的浏览器中。当用户访问网站时,如果他们的浏览器或操作系统的钥匙串中没有证书,我们会将他们重定向到自定义 403 页面。这是使用以下 Apache 配置实现的。

<VirtualHost *:443>
    ServerName host.tld
    ServerAlias www.host.tld

    ServerAdmin [email protected]
    DocumentRoot /var/www/path

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    SSLEngine on
    SSLProtocol             all -SSLv2 -SSLv3

    SSLCertificateFile /etc/ssl/host/host.crt
    SSLCertificateKeyFile /etc/ssl/host.key
    SSLCACertificateFile /etc/ssl/cacert.pem
    SSLVerifyClient optional
    SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire
    SSLVerifyDepth 10
#   SSLCARevocationPath /etc/ssl/crl
    SSLCARevocationFile /etc/ssl/ca.crl
    SSLCARevocationCheck chain

    RewriteEngine        on
    RewriteCond %{ENV:REDIRECT_STATUS} ^$
    RewriteCond     %{SSL:SSL_CLIENT_VERIFY} !=SUCCESS
    RewriteRule     .? - [F]
    ErrorDocument 403 /403.html
    
</VirtualHost>

我想更进一步,引入一些条件,如果他们有证书,就加载特定的 DocumentRoot,如果他们没有客户端证书,就加载另一个 DocumentRoot。

总结:website.com

  • 用户 A 使用客户端 SSL 访问,从 /var/www/has_ssl 提供 website.com
  • 用户 B 无需客户端 SSL 即可访问,从 /var/www/no_ssl 提供 website.com

如果为空,我可以用来%{SSL:SSL_CLIENT_S_DN_CN} =""重定向到路径,但我不确定如何根据证书的存在重写 DocumentRoot。

我已经为此苦苦挣扎了几天。任何帮助或指点都将不胜感激。

答案1

据我所知,您无法有条件地设置DocumentRoot。但是,您可以使用 mod_rewrite 在内部重写请求,就像在未设置客户端 SSL 时返回 403 响应一样。

例如,如果您设置:

DocumentRoot /var/www

然后在内部重写所有请求以使其/var/www/has_ssl成功或/var/www/no_ssl失败。

RewriteEngine on

RewriteCond %{SSL:SSL_CLIENT_VERIFY} !=SUCCESS
RewriteRule ^ /no_ssl%{REQUEST_URI} [L]

RewriteCond %{SSL:SSL_CLIENT_VERIFY} =SUCCESS
RewriteRule ^ /has_ssl%{REQUEST_URI} [L]

为了防止直接访问/no_ssl/has_ssl子目录,您可以实施外部重定向上面的重写会从请求中删除子目录。例如:

RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^/(no_ssl|has_ssl)(.*) /$1 [R=301,L]

相关内容