我希望能够检测浏览器是否支持SNI-Server Name Indication。我希望将不合规的客户重定向到不同的地址。
我正在考虑通过 SSL 加载一些内容并确保它被安全传输。否则浏览器不支持 SNI。这可以做到吗?
我希望能够检测浏览器是否支持SNI-Server Name Indication。我希望将不合规的客户重定向到不同的地址。
我正在考虑通过 SSL 加载一些内容并确保它被安全传输。否则浏览器不支持 SNI。这可以做到吗?
您可以设置一个支持 SNI 的服务器,提供两个主机名,在您需要 SNI 的地方和一个作为后备解决方案的地方,都提供他们托管的名称。
类似于以下内容:
https://www.example.com/name
返回一个表示说I'm www.example.com
https://www.example.net/name
返回I'm www.example.net
(并且需要 SNI)。如果您发出 XHR 请求https://www.example.net/name
并返回www.example.com
,则浏览器不支持 SNI。
不确定这是否是想要的,但有这个
RewriteEngine on
# 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]
如果旧浏览器尝试使用需要 SNI 的站点,则它将被重定向(在这种情况下返回 http 并且页面显示浏览器太旧)。但是你总是会得到一个错误。这是无法避免的。浏览器说你好 IP....,而 apache 回复你好,这里是我的证书。如果浏览器在 hello apache 中不提供 SNI,则只发送默认(即错误)证书。浏览器然后抱怨。
如果您想在切换到 https 之前从 http 获取它,那么您可以在 htaccess 中放置类似的内容
#Set $_SERVER['SSL_TLS_SNI'] for php = %{SSL:SSL_TLS_SNI} or value
SetEnv SSL_TLS_SNI %{SSL:SSL_TLS_SNI}
然后在您的页面中从默认域执行 https 获取(默认因此浏览器不会说存在安全错误)。如果 SNI 正在工作,则 php $_SERVER['SSL_TLS_SNI'] 将具有域名,否则它将具有 %{SSL:SSL_TLS_SNI}。这段代码可以改进,但你明白了。
您只能在需要之前测试 SNI 支持。也就是说,您不能强制用户使用 SNI HTTPS,然后如果他们不支持它就回退,因为他们将收到这样的错误(来自 Windows XP 上的 Chrome)而无法继续。
因此(不幸的是)用户实际上必须从不安全的 HTTP 连接开始,然后只有在他们支持 SNI 时才进行升级。
您可以通过以下方式检测 SNI 支持:
远程脚本
从您的纯 HTTP 页面,<script>
从您的目标 SNI HTTPS 服务器加载一个,如果脚本加载并正确运行,您就知道浏览器支持 SNI。
跨域 AJAX (CORS)
与选项 1 类似,您可以尝试执行从 HTTP 页面到 HTTPS 的跨域 AJAX 请求,但请注意 CORS仅支持有限的浏览器。
嗅探用户代理
这可能是最不可靠的方法,您需要决定是拥有一个已知不支持它的浏览器(和操作系统)的黑名单,还是一个已知支持它的系统的白名单。
我们知道 Windows XP 及以下所有版本的 IE、Chrome 和 Opera 都不支持 SNI。有关支持的浏览器的完整列表,请参阅CanIUse.com。
自从 commercerack 为所有站点升级到 SNI 以来,我们遇到了同样的问题。(用户开始结帐并遇到令人讨厌的 SSL 问题)。
随意将此作为起点。随着浏览器列表的增长,我会更新,但它现在在 XP + Android 2.0-2.2 上运行 IE。
https://github.com/brianhorakh/html-sni-useragent-sniffer-warning