说,我有一个网站mywebsite.com
,使用 Apache Httpd 托管。现在我想要的是,只要有任何用户类型mywebsite.com
,或者www.mywebsite.com
如果浏览器支持 SNI,那么它应该重定向到https://www.mywebsite.com
else 重定向到http://www.mywebsite.com
.
那么,实现它的最有效方法是什么?
下面的代码应该可以工作
Options -Indexes +FollowSymLinks
RewriteEngine on
RewriteCond %{HTTP_HOST} ^mywebsite.com$
RewriteCond %{HTTPS} (on|off)
RewriteRule ^(.*)$ http://www.mywebsite.com/$1 [R=302,L]
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
RewriteCond %{HTTP_USER_AGENT} !Windows\sNT\s5
RewriteCond %{HTTP_USER_AGENT} !^(.*.symbian.*) [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.blackberry.*) [NC]
RewriteRule ^(.*)$ https://www.mywebsite.com/$1 [R=302,L]
在这里,我们忽略了大多数不支持 SNI 的浏览器,因此对于它们来说,只会加载 http 版本。
更好的解决方案是
#Test if new browser and if so redirect to https
#new browser is not MSIE 5-8, not Android 0-3,
#not any symbian and not any blackbery
RewriteCond %{HTTPS} off
RewriteCond %{HTTP_USER_AGENT} !MSIE\ [5-8] [NC]
RewriteCond %{HTTP_USER_AGENT} !Android.*(Mobile)?\ [0-3] [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.symbian.*) [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.blackberry.*) [NC]
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
这忽略了 MSIE 5-8,它排除了 XP 上的所有 IE,以及 VISTA 上可以工作的一些 IE。但允许 XP 与 chrome、firefox、opera,所有这些都支持 XP 上的 SNI。这至少允许 XP 用户使用 https。同样,它假设所有 symbian、blackbery 都没有 sni。那个android 3可以(我被告知哪些平板电脑,手机需要4个)。
对于不同的解决方案,您可以拥有
#Could use this to set $_SERVER['SSL_TLS_SNI'] for php
SetEnv SSL_TLS_SNI %{SSL:SSL_TLS_SNI}
这会将 $_SERVER['SSL_TLS_SNI'] 设置为 %{SSL:SSL_TLS_SNI} (是的可能是更好的代码)或域名。如果您知道 apache 返回的默认证书是什么并且可以访问该域,那么在其他域中,您可以让 php 对默认域进行测试 https,然后在之前检查 $_SERVER['SSL_TLS_SNI'] 以测试 SNI去https。
请注意,如果非 sni 浏览器对需要 sni 的站点执行 https,则无法避免错误消息。你能做的最好的就是
# Test if SNI will work and if not redirect to too old browser page
RewriteCond %{HTTPS} on
RewriteCond %{SSL:SSL_TLS_SNI} =""
RewriteRule ^ http://www.example.com/too-old-browser [L,R=307]
用户需要接受浏览器错误并继续访问网站,之后他会被重定向到 http 和错误页面。
这是我根据上面的答案使用的。
RewriteRule (.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=302]
RewriteCond %{HTTP_USER_AGENT} !MSIE\s7
RewriteCond %{HTTP_USER_AGENT} !Windows\sNT\s5
RewriteCond %{HTTP_USER_AGENT} !Android.*(Mobile)?\ [0-3] [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.symbian.*) [NC]
RewriteCond %{HTTP_USER_AGENT} !^(.*.blackberry.*) [NC]
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP_HOST} !^$
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteCond %{HTTPS}s ^on(s)|
RewriteRule ^ http%1://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
如果未列出 useragent,这将首先重写为 http,然后重写为 https。我不知道两次重写是否不好,但我确信谷歌和其他相关机器人更喜欢索引 https。这种方式可以实现(我认为:)
我这样做的倒退方式,但它似乎工作。我相信您最好将浏览器列入黑名单并将它们导航到 HTTP 而不是将浏览器列入白名单,因为要添加的浏览器太多了。
每个站点都不同,根据安全性,上述可能是一种选择。
请让我知道你的想法。
您可以设置第二个服务器,该服务器只能与 SNI 一起使用,并使您的第一个站点上的页面向它发出 Ajax 请求(如果需要,可能带有一些标识符)。
如果客户端不支持 SNI,则服务器将为请求的主机名提供无效证书。因此,该 Ajax 请求将不起作用。您可以让您的初始页面对该故障做出反应,作为不支持 SNI 的指示。
当然,这并不完美,但这可能比必须依赖于明确的用户代理列表(取决于您拥有的约束)更好。这将更像是直接测试客户端功能。