https重定向网络解决方案

时间:2011-01-13 23:52:44

标签: .htaccess redirect https

我使用Network Solutions作为托管服务提供商,提供UNIX托管包。我需要将某些页面重定向到https(登录等)。经过大量测试后,我最终得到了以下.htaccess条目:

RewriteEngine on

RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://[domain_redacted]/$1 [R=301,L]

这导致了无限重定向循环。在与Network Solutions讨论后,他们告诉我需要301重定向(显然我正在做的不是301重定向......),所以我在.htaccess中尝试了以下内容:

Redirect 301 / https://[domain_redacted]/

当然,这会导致无限循环,正如人们所期望的那样。由于这些方法都不起作用,我在我的服务器上放了以下PHP脚本来通过PHP测试https检测:

<?php 
if(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') { 
    echo 'HTTPS IS ON';
} else {
    echo 'HTTPS IS OFF';
} 
?>

通过HTTP和HTTPS请求此页面时,脚本将返回OFF。

那么,在Apache或PHP中检测HTTPS服务器端还有哪些其他方法?

5 个答案:

答案 0 :(得分:3)

我只是这样问我可以回答这个问题,主要是因为我无法在任何地方找到解决方案。

背景: Network Solutions处理共享主机系统的方式,实际上并不连接到服务器,而是连接到代理服务器(这很有意义)。执行https重定向时,例如:

RewriteEngine on

RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://[domain_redacted]/$1 [R=301,L]

事实上,您确实将页面重定向到HTTPS。但是,您正在使用代理服务器而不是托管服务器执行HTTPS事务。代理服务器通过端口80将您的HTTPS连接转换为HTTP。当尝试使用.htaccess检测到此情况时,服务器看不到HTTPS,因为托管服务器和代理之间的连接始终是端口80上的HTTP。 PHP从Apache中提取HTTPS变量,它将通过.htaccess检测HTTP具有相同的结果。

因此,除非我弄错了,否则在使用Network Solutions的共享主机时,无法执行自引用HTTP到HTTPS重定向。请求必须以某种方式更改(通过更改URI或查询字符串),以便服务器检测更改。当然,这是完全可欺骗的(例如,无论你如何更改URI /查询字符串,只需将其作为http键入浏览器,服务器永远不会知道),否定HTTPS的全部要点。

我尝试检查%{HTTP_REFERER}是否引用了自己,但它没有使用mod_rewrite。

我能想到的唯一解决方法是通过javascript进行客户端检测。这有其自身的缺陷(NoScript等)。但我无法想出另一个问题的解决方案。以下代码将近似301重定向。

if(document.URL.match(/^https/i) == null) {
    var NetworkSolutionsSucks = document.createElement('meta');
    with (NetworkSolutionsSucks) {
        httpEquiv = 'refresh';
        content = '0;url=' + document.URL.replace(/^http/i,'https');
    }
    document.head.appendChild(NetworkSolutionsSucks);

    var msg = document.createElement('div');
    with (msg) {
        innerHTML = 'This page requires a secure connection, you are being redirected.<br><br>';
        innerHTML += 'If the page does not load, please click <a href="' + document.URL.replace(/^http/i,'https') + '">Here</a>';
    }
    var newBody = document.createElement('body');

    newBody.appendChild(msg);
    document.replaceChild(newBody, document.body);
}

将上述脚本包含在您要强制HTTPS的任何文档的标题中(强制HTTP留作读者练习 - 这是一个更简单的脚本,不需要手动重定向某些失败)。你应该使用一个noscript标签(显然);您可以使用以下内容:

<noscript id="networkSolutionsHTTPSRedirect">This site requires javascript in order to operate properly. Please enable javascript and refresh this page.</noscript>
<style type="text/css">#networkSolutionsHTTPSRedirect{position: fixed; height: 100%; width: 100%; top: 0; left: 0; z-index: 500;}</style>
<script type="text/javascript">
<!--
document.getElementById("networkSolutionsHTTPSRedirect").style.visibility = "hidden";
document.getElementById("networkSolutionsHTTPSRedirect").style.display = "none";
-->
</script>

编辑:我想出了一种方法来做这个服务器端:

如果您在每个页面上执行以下操作,则可以尝试强制整个站点使用HTTPS:

<?php
if((!isset($_ENV['HTTP_REFERER']) || preg_match('/^http[s]{0,1}:\/\/' . $_ENV['SERVER_NAME'] . '/i',$_ENV['HTTP_REFERER']) == 0) && !isset($_ENV[HTTP_X_HTTPS_REDIRECT])) {
    header('X-HTTPS-REDIRECT: true\n');
    header('Location:' . preg_replace('/^http/','https', $_ENV['SCRIPT_URI']));
}
?>

这应该为所有没有为您的站点设置HTTP_REFERER的请求引入重定向,并且不带有您注入的自定义X-HTTPS-REDIRECT标头。这并不能真正检测到HTTPS,而是执行合理的传真(至少在服务器端)。

当然,您可以修改正则表达式,以便只有某些网站需要通过将REFERER与您想要保护的域部分相匹配才能成为HTTPS,然后取消测试以强制使用HTTP。

答案 1 :(得分:2)

我也有网络解决方案作为我的提供商。最后一次使用PHP编写脚本也没有用,导致无限循环。

网络解决方案提供以下代码作为Javascript中从http://到https://的最佳重定向,说没有办法在服务器端执行此操作。

    <script language="javascript">
    if (document.location.protocol != "https:")
    {
    document.location.href = "https://subdomain.yourdomain.com" + document.location.pathname;
    };
    </script>

可在此处找到有关该主题的信息。 http://www.networksolutions.com/support/ssl-redirects/

答案 2 :(得分:0)

使用以下命令仅强制某些页面为https。在您强制http的部分中,只需包含以否定格式强制使用https的部分/页面。

这样的事情,也许是:(。htaccess)

Options +FollowSymLinks
RewriteEngine On
RewriteBase /

# Force https for mode= login, account or register, and the /admin directory:
RewriteCond %{HTTPS} !=on
RewriteCond %{QUERY_STRING} mode=(login|account|register) [OR]
RewriteCond %{REQUEST_URI} admin/
RewriteRule (.+) https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

# force http for all NON login, account, register (query string)
# and anything else outside the /admin directory
RewriteCond %{HTTPS} on
RewriteCond %{QUERY_STRING} !mode=(login|account|register)
RewriteCond %{REQUEST_URI} !admin/
RewriteRule (.+) http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

答案 3 :(得分:0)

PHP变量:

$_ENV['SCRIPT_URI'] 

将返回完整的请求字符串,包括协议。

<?php 
if(preg_match('/^https/i',$_ENV['SCRIPT_URI']) == 0) {
    header('Location: ' . preg_replace('/^http/i','https', $_ENV['SCRIPT_URI']));
} 
?>

答案 4 :(得分:0)

这是使用 Networksolutions 重定向的唯一干净方式。花了我几个小时的测试。最适合 SEO。 Network Solutions 是一个具有挑战性的托管平台。

这将起作用 .htaccess 您只需将 changeexample.com 替换为您的域即可。很简单。

## Base Redirects ##

# Turn on Rewrite Engine
RewriteEngine On

# Remove trailing slash from non-filepath urls
RewriteCond %{REQUEST_URI} /(.+)/$
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ https://changeexample.com/%1 [R=301,L]

# Include trailing slash on directory 
RewriteCond %{REQUEST_URI} !(.+)/$
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+)$ https://changeexample.com/$1/ [R=301,L]

# Force HTTPS and remove WWW
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [OR,NC]
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ https://changeexample.com/$1 [R=301,L]

祝你好运!这是截至 2021 年 5 月 14 日的最新数据