我正在寻找一种方法,将支持 SNI 的网络浏览器从 http 重定向到 https,以及将不支持 SNI 的网络浏览器从 https 重定向到 http。第二种情况很重要,例如,如果用户收到通过邮件发送的 https url 并使用旧浏览器打开它。
我想避免使用用户代理,因为我不想跟踪新的浏览器版本并相应地更新配置文件,例如 .htaccess。
因此,我使用 javascript 来检测 SNI 支持并重定向网络浏览器。以下代码检查连接是否受 SSL 保护。如果不是 SSL 安全的,它会检查 SNI 支持并在支持 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>
如果用户第一次访问该网站并使用 SSL 加密,他会被重定向到 http url 以运行 javascript 代码。否则,旧浏览器会打开受保护的网站并显示错误消息。
RewriteCond %{HTTPS} =on
RewriteCond %{HTTP_REFERER} !^http(s)?://(www\.)?example\.org [NC]
RewriteRule .* http://%{HTTP_HOST}%{REQUEST_URI} [R=302,L]
更新 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>
更新 2: 我们希望避免重定向爬虫。
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]
更新 3: 我们通过 PHP 使用更可靠的 https 检测(无重定向循环)。
<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>
开放式问题:
- 如何完全避免使用用户代理?如果不可能,是否缺少任何重要的网络爬虫用户代理?
- 使用更新 3 中描述的方法,后退按钮无法正常工作。如果用户从 http 转发到 https,然后单击后退按钮,他将被重定向到 http,然后再次从 http 到 https。这个问题可以通过 location.replace() 解决,但该方法不支持referrer。
- 在以下示例中,如何使用 location.replace() 和http://www.example.org作为推荐人?示例:google.de -> http://www.example.org -> https://www.example.org -> 后退按钮单击 -> http://www.example.org(不重定向到 google.de !!!) -> https://www.example.org
- 如果浏览器不支持javascript,则强制使用http。
- 这种方法有什么未知的问题吗?
学分: