检测和重定向 SNI 支持的浏览器的最有效代码是什么?

问题描述 投票:0回答:5

假设我有一个网站

mywebsite.com
,使用 Apache Httpd 托管。现在我想要的是,每当任何用户输入
mywebsite.com
www.mywebsite.com
并且如果浏览器支持 SNI,那么它应该重定向到
https://www.mywebsite.com
,否则重定向到
http://www.mywebsite.com

那么,最有效的实现方法是什么?

.htaccess ssl sni
5个回答
2
投票

下面的代码应该可以工作

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 版本。


1
投票

更好的解决方案是

  #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、blackberry 都没有 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 和错误页面。


1
投票

这是我根据上面的答案使用的。

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]

这将首先重写为 http,然后如果未列出 useragent,则重写为 https。 我不知道两次重写是否不好,但我确信谷歌和其他相关机器人更喜欢索引 https。这种方式可以实现这一点(我认为:)

我的做法倒退,但似乎有效。我确信您最好将浏览器列入黑名单并将其导航到 HTTP,而不是将浏览器列入白名单,因为要添加的浏览器太多了。

每个站点都不同,根据安全性,上述可能是一个选项。

请让我知道您的想法。


0
投票

您可以设置第二个仅与 SNI 配合使用的服务器,并使第一个站点上的页面向其发出 Ajax 请求(如果需要,可能会使用一些标识符)。

如果客户端不支持 SNI,服务器将为所请求的主机名提供无效的证书。因此,该 Ajax 请求将不起作用。您可以让您的初始页面对该故障做出反应,以表明不支持 SNI。

当然,这并不完美,但这可能比必须依赖于用户代理的显式列表更好(取决于您所拥有的约束)。这更符合直接测试客户端功能的思路。


0
投票

以下代码的灵感来自于user3281096的回答

尚未工作,必须考虑草案

由于大多数浏览器现在都支持 HTTPS,因此我们的想法是避免双重重定向,并且仅当浏览器不支持 HTTPS 时才重定向到 HTTP。 为此,定义了一个名为 HTTP_ONLY 的环境变量,如果浏览器属于某个“黑”名单,则将其设置为 1 (= true)。

因为

<If>
<Else>
指令仅在 Apache 2.4 中可用,所以我不得不使用
<IfDefine>
来代替。

环境变量和

<IfDefine>
使用起来似乎很棘手,到目前为止我找不到让以下代码正常工作的方法。

测试是使用 Internet Explorer 11 执行的,方法是取消注释行

BrowserMatch "Trident/7" HTTP_ONLY=1
,人为将此浏览器插入到仅 HTTP 浏览器列表中。

如果您知道如何调整此代码以使其工作,请发表评论。

RewriteEngine On

RewriteBase /

SetEnv HTTP_ONLY 0

# Set a black list of (some) old browsers that do not support HTTPS
BrowserMatch "MSIE[5-8]" HTTP_ONLY=1
BrowserMatchNoCase "symbian" HTTP_ONLY=1
BrowserMatchNoCase "blackberry" HTTP_ONLY=1

# Activate next line for testing purposes with Internet Explorer 11
# like if it was Internet Explorer 5 to 8. Not sure that it works properly.
# BrowserMatch "Trident/7" HTTP_ONLY=1

# If the browser only supports HTTP, redirect to HTTP instead of HTTPS.
<IfDefine HTTP_ONLY>
  RewriteCond %{ENV:HTTP_ONLY} true
  RewriteRule ^(.*)$ http://www.somesite.ext/$1 [R=302,L]
</IfDefine>

# Redirect to HTTPS. Next two lines must be active on remote server.
<IfDefine HTTP_ONLY>
  RewriteCond %{ENV:HTTP_ONLY} false
  RewriteCond %{HTTPS} !on
  RewriteRule ^(.*)$ https://www.somesite.ext/$1 [L,R=301]
</IfDefine>

# Force “www.somesite.ext” instead of just “somesite.ext”
#RewriteCond %{HTTP_HOST} .
#RewriteCond %{HTTP_HOST} !^www\.somesite\.ext [NC]
#RewriteRule (.*) https://www.somesite.ext/$1 [L,R=301]
© www.soinside.com 2019 - 2024. All rights reserved.