【问题标题】:https redirect for Network Solutions网络解决方案的 https 重定向
【发布时间】:2011-06-08 20:53:35
【问题描述】:

我使用网络解决方案作为带有 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 服务器端?

【问题讨论】:

  • 你知道Apache和PHP运行的是什么版本吗?
  • PHP 版本 5.2.13 Apache/2.2.14 (Unix) FrontPage/5.0.2.2635

标签: .htaccess redirect https


【解决方案1】:

使用以下命令仅强制某些页面使用 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]

【讨论】:

  • 它不起作用 - 请参阅下面的解决方案。抱歉,我只是问了,所以我可以回答我自己的问题,希望能在我的情况下帮助其他人。
  • 我发布的代码可以工作,但如果是代理服务器,我不知道。我不知道网络解决方案都在代理服务器上运行。
  • 你是对的,你的代码对于任何理智的实现都是 100% 正确的。但即使是 HTTPS 查询,网络解决方案共享主机包上的 %{HTTPS} 仍然处于关闭状态(因为目标服务器没有收到 HTTPS 请求,它正在接收 HTTP 请求)。
  • 顺便说一下,我不确定是否所有网络解决方案的东西都在代理后面;托管人员让我相信,如果我升级到他们作为服务器管理员的软件包之一(而不是共享托管的一部分),它可能会有所不同,但他们不能保证,而且可能更贵比这么小的项目值得。
【解决方案2】:

我问只是为了回答这个问题,主要是因为我在任何地方都找不到解决方案。

背景: Network Solutions 处理其共享托管系统的方式,您实际上并没有连接到服务器,而是连接到代理服务器(这是有道理的)。当您执行 https 重定向时:

RewriteEngine on

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

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

因此,除非我弄错了,否则在网络解决方案的共享主机上执行自引用 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 与您想要保护的域部分进行匹配,然后取消测试以强制使用 HTTP,从而只有某些网站需要 HTTPS。

【讨论】:

    【解决方案3】:

    PHP 变量:

    $_ENV['SCRIPT_URI'] 
    

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

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

    【讨论】:

    • 或者,您可以寻找 '/^http:\/\//i' 作为您的正则表达式来专门强制 http 识别,而不是仅仅识别非 https - 上面的解决方案将(可能) 导致在 http 和 https 以外的协议上出现无限循环。
    【解决方案4】:

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

    Network Solutions 提供以下代码作为 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/

    【讨论】:

    • @Siddharth,你可以把它放在任何你需要确保用户使用 https:// 而不是 http:// 的文件中。
    【解决方案5】:

    这是使用 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 日的最新数据

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-17
      • 2013-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多