强制SSL并处理不支持SNI的浏览器
我正在寻找一种方法,将支持SNI的WebBrowser从http重定向到https,并将不支持SNI的WebBrowser从https重定向到http。第二种情况很重要,例如,如果用户收到通过邮件发送的https url,并使用旧浏览器打开该url 我想避免使用用户代理,因为我不想跟踪新的浏览器版本并相应地更新配置文件,例如.htaccess 因此,我使用javascript检测SNI支持并重定向webbrowser。以下代码检查连接是否受SSL保护。如果SSL不安全,它将检查是否支持SNI,并在支持SNI时重定向浏览器:强制SSL并处理不支持SNI的浏览器,ssl,https,sni,Ssl,Https,Sni,我正在寻找一种方法,将支持SNI的WebBrowser从http重定向到https,并将不支持SNI的WebBrowser从https重定向到http。第二种情况很重要,例如,如果用户收到通过邮件发送的https url,并使用旧浏览器打开该url 我想避免使用用户代理,因为我不想跟踪新的浏览器版本并相应地更新配置文件,例如.htaccess 因此,我使用javascript检测SNI支持并重定向webbrowser。以下代码检查连接是否受SSL保护。如果SSL不安全,它将检查是否支持SNI,并
<head>
<script type="text/javascript">
if (window.location.protocol != "https:") {
var img=document.createElement('img');
img.src='https://www.example.org/favicon.png';
img.onload = function() {
window.location.href = "https:" + window.location.href.substring(window.location.protocol.length);
}
img.style.display='none';
document.body.appendChild(img);
}
</script>
...
</head>
更新1:
有一个重定向循环,因为javascript不提供引用。
此解决方案似乎避免了循环:
<body>
<form style="display:none;" method="get" name="redirect"></form>
<script type="text/javascript">
if (window.location.protocol != "https:") {
var img=document.createElement('img');
img.src='https://www.example.org/favicon.png';
img.onload = function() {
document.redirect.action = "https:" + window.location.href.substring(window.location.protocol.length);
document.forms['redirect'].submit();
}
img.style.display='none';
document.body.appendChild(img);
}
</script
...
</body>
更新3:
我们通过PHP使用更可靠的https检测(无重定向循环)
var img=document.createElement('img');
img.src=https://www.example.org/favicon.png';
img.onload=函数(){
var redirect_form=document.forms[“redirect”];
重定向_form.action=“https:”+window.location.href.substring(window.location.protocol.length);
重定向_form.submit();
}
img.style.display='none';
文件.正文.附件(img);
...
未决问题:
- 如何完全避免使用用户代理?如果不可能,是否缺少任何重要的web爬虫用户代理
- 使用更新3中描述的方法,“后退”按钮无法正常工作。如果用户从http转发到https,然后单击后退按钮,他将被重定向到http,然后再次从http转发到https。此问题可以通过location.replace()解决,但该方法不支持referer
- 在下面的示例中,如何使用location.replace()作为引用?示例:google.de->->->->返回按钮单击->(不重定向到google.de!!!)->
- 如果浏览器不支持javascript,它将被迫使用http
- 这种方法是否存在未知问题
由于各种问题,我决定放弃htaccess规则。使用以下代码,支持Javascript和SNI的web浏览器将重定向到SSL安全页面,而无需检查用户代理:
<body>
<?php if (empty($_SERVER["HTTPS"])) { ?>
<form style="display:none;" method="get" name="redirect"></form>
<script type="text/javascript">
var img=document.createElement('img');
img.src='https://www.example.org/favicon.png';
img.onload = function() {
var redirect_form = document.forms["redirect"];
redirect_form.action = "https:" + window.location.href.substring(window.location.protocol.length);
redirect_form.submit();
}
img.style.display='none';
document.body.appendChild(img);
</script>
<?php } ?>
...
</body>
不支持SNI的旧web浏览器如果通过https()访问页面,则会重定向到http:
RewriteCond %{HTTPS} =on
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example\.org [NC]
RewriteCond %{HTTP_USER_AGENT} !(googlebot|bingbot|baiduspider) [NC]
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
<body>
<?php if (empty($_SERVER["HTTPS"])) { ?>
<form style="display:none;" method="get" name="redirect">
<input type="hidden" name="redirected" value="true" />
</form>
<script type="text/javascript">
var img=document.createElement('img');
img.src='https://www.example.org/favicon.png';
img.onload = function() {
var redirect_form = document.forms["redirect"];
redirect_form.action = "https:" + window.location.href.substring(window.location.protocol.length);
redirect_form.submit();
}
img.style.display='none';
document.body.appendChild(img);
</script>
<?php } ?>
...
</body>
<body>
<?php if (empty($_SERVER["HTTPS"])) { ?>
<form style="display:none;" method="get" name="redirect"></form>
<script type="text/javascript">
var img=document.createElement('img');
img.src='https://www.example.org/favicon.png';
img.onload = function() {
var redirect_form = document.forms["redirect"];
redirect_form.action = "https:" + window.location.href.substring(window.location.protocol.length);
redirect_form.submit();
}
img.style.display='none';
document.body.appendChild(img);
</script>
<?php } ?>
...
</body>
RewriteCond %{HTTPS} =on
RewriteRule ^(.*)$ - [env=proto:https]
RewriteCond %{HTTPS} !=on
RewriteRule ^(.*)$ - [env=proto:http]
RewriteCond %{THE_REQUEST} \?\ HTTP [NC]
RewriteRule .? %{ENV:proto}://%{HTTP_HOST}%{REQUEST_URI}? [R=301,L]
SetEnv SSL_TLS_SNI %{SSL:SSL_TLS_SNI}
RewriteCond %{HTTPS} =on
RewriteCond %{HTTP_USER_AGENT} MSIE\s6 [NC,OR]
RewriteCond %{HTTP_USER_AGENT} Windows\sNT\s5 [NC,OR]
RewriteCond %{HTTP_USER_AGENT} Android.*(Mobile)?\ [0-3] [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^(.*.symbian.*) [NC,OR]
RewriteCond %{HTTP_USER_AGENT} ^(.*.blackberry.*) [NC]
RewriteCond %{SSL:SSL_TLS_SNI} =""
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R=307,L]