【问题标题】:How can I force users to access my page over HTTPS instead of HTTP?如何强制用户通过 HTTPS 而不是 HTTP 访问我的页面?
【发布时间】:2010-09-10 07:01:09
【问题描述】:

我只有一个页面,我想强制作为 HTTPS 页面(Apache 上的 PHP)访问。如何在不使整个目录需要 HTTPS 的情况下做到这一点?或者,如果您从 HTTP 页面向 HTTPS 页面提交表单,它是通过 HTTPS 而不是 HTTP 发送的吗?

这是我的例子:

http://www.example.com/some-page.php

我希望它只能通过以下方式访问:

https://www.example.com/some-page.php

当然,我可以将指向该页面的所有链接都指向 HTTPS 版本,但这并不能阻止某些傻瓜故意通过 HTTP 访问它...

我想到的一件事是在 PHP 文件的标头中放置一个重定向,以确保他们正在访问 HTTPS 版本:

if($_SERVER["SCRIPT_URI"] == "http://www.example.com/some-page.php"){
  header('Location: https://www.example.com/some-page.php');
}

但这不可能是正确的方法,不是吗?

【问题讨论】:

标签: php apache ssl https


【解决方案1】:
if(location.protocol!=='https:'){location.replace(`https:${location.href.substring(location.protocol.length)}`);}

【讨论】:

    【解决方案2】:

    作为替代方案,您可以使用 X-Forwarded-Proto 标头强制重定向到 HTTPS。

    在 .htaccess 文件中添加这些行

    ### Force HTTPS
    RewriteCond %{HTTP:X-Forwarded-Proto} !https
    RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
    

    【讨论】:

    • 这也修复了重定向过多问题
    【解决方案3】:

    如果您想使用 PHP 来执行此操作,那么这种方式对我来说非常有效:

    
    <?php
    
    if(!isset($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] != "on") {
        header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"], true, 301);
        //Prevent the rest of the script from executing.
        exit;
    }
    ?>
    
    

    它检查 $_SERVER 超全局数组中的 HTTPS 变量,看它是否等于“on”。如果变量不等于on。

    【讨论】:

      【解决方案4】:

      PHP方式:

      $is_https=false;
      if (isset($_SERVER['HTTPS'])) $is_https=$_SERVER['HTTPS'];
      if ($is_https !== "on")
      {
          header("Location: https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
          exit(1);
      }
      

      Apache mod_rewrite 方式:

      RewriteCond %{HTTPS} !=on
      RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
      

      【讨论】:

      • 我更喜欢 PHP 方式,因为在某些情况下我希望覆盖 SSL 的要求。例如,对 API 的本地访问以及 Mozilla Thunderbird 的自动配置等内容。
      • PHP 方法非常适合我,强烈推荐。
      【解决方案5】:

      也许这个可以帮助你,我就是这样为我的网站做的,它就像一个魅力:

      $protocol = $_SERVER["HTTP_CF_VISITOR"];
      
      if (!strstr($protocol, 'https')){
          header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
          exit();
      }
      

      【讨论】:

        【解决方案6】:

        好的.. 现在有很多东西,但没有人真正完成 “安全”的问题。对我来说,使用不安全的东西是可笑的。

        除非你把它当作诱饵。

        $_SERVER 传播可以根据知道如何更改的人的意愿进行更改。

        正如 Sazzad Tushar Khan 和 thebigjc 所说,您也可以使用 httaccess 来执行此操作,这里有很多包含它的答案。

        只需添加:

        RewriteEngine On
        RewriteCond %{SERVER_PORT} 80
        RewriteRule ^(.*)$ https://example.com/$1 [R,L]
        

        到您的 .httaccess 中的内容结束,仅此而已。

        我们仍然没有使用这 2 个工具尽可能安全。

        剩下的很简单。如果缺少属性即...

        if(empty($_SERVER["HTTPS"])){ // SOMETHING IS FISHY
        }
        
        if(strstr($_SERVER['HTTP_HOST'],"mywebsite.com") === FALSE){// Something is FISHY
        }
        


        还说您已更新 httaccess 文件并检查:

        if($_SERVER["HTTPS"] !== "on"){// Something is fishy
        }
        

        您可以检查更多变量,即..

        HOST_URI(如果有关于它的静态属性要检查)

        HTTP_USER_AGENT(同一会话不同的值)

        所以我想说的是,当答案在于组合时,不要只满足于其中一个。

        有关更多 httaccess 重写信息,请参阅 docs-> http://httpd.apache.org/docs/2.0/misc/rewriteguide.html

        这里有一些堆栈 -> Force SSL/https using .htaccess and mod_rewrite

        Getting the full URL of the current page (PHP)
        命名一对。

        【讨论】:

        • 但现在我收到以下错误:ERR_TOO_MANY_REDIRECTS。我该如何解决这个问题?
        【解决方案7】:

        对于那些使用 IIS 的用户,在 web.config 中添加这一行会有所帮助:

        <httpProtocol>
            <customHeaders>
                <add name="Strict-Transport-Security" value="max-age=31536000"/>
            </customHeaders>
        </httpProtocol>
        <rewrite>
            <rules>
                <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                      <match url="(.*)" />
                      <conditions>
                         <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                      </conditions>
                      <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
                 </rule>
            </rules>
        </rewrite>
        

        完整的示例文件

        <?xml version="1.0" encoding="UTF-8"?>
        <configuration>
            <system.webServer>
                <httpProtocol>
                    <customHeaders>
                        <add name="Strict-Transport-Security" value="max-age=31536000"/>
                     </customHeaders>
                </httpProtocol>
                <rewrite>
                    <rules>
                        <rule name="HTTP to HTTPS redirect" stopProcessing="true">
                              <match url="(.*)" />
                              <conditions>
                                 <add input="{HTTPS}" pattern="off" ignoreCase="true" />
                              </conditions>
                              <action type="Redirect" redirectType="Found" url="https://{HTTP_HOST}/{R:1}" />
                         </rule>
                    </rules>
               </rewrite>
           </system.webServer>
        </configuration>
        

        【讨论】:

        • 这个问题专门询问 Apache,而不是 IIS。
        • A) 它没有标记 apache。 Apache 在引号之间被提及。 B)它是一个一般性的问题,一般与 apache 无关。适用于多个支持php的网络服务器
        【解决方案8】:
        // Force HTTPS for security
        if($_SERVER["HTTPS"] != "on") {
            $pageURL = "Location: https://";
            if ($_SERVER["SERVER_PORT"] != "80") {
                $pageURL .= $_SERVER["SERVER_NAME"] . ":" . $_SERVER["SERVER_PORT"] . $_SERVER["REQUEST_URI"];
            } else {
                $pageURL .= $_SERVER["SERVER_NAME"] . $_SERVER["REQUEST_URI"];
            }
            header($pageURL);
        }
        

        【讨论】:

          【解决方案9】:

          我已经通过许多解决方案来检查 $_SERVER[HTTPS] 的状态,但它似乎不可靠,因为有时它没有设置或设置为开、关等,导致脚本到内部循环重定向。

          如果您的服务器支持 $_SERVER[SCRIPT_URI]

          ,这是最可靠的解决方案
          if (stripos(substr($_SERVER[SCRIPT_URI], 0, 5), "https") === false) {
              header("location:https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");
              echo "<meta http-equiv='refresh' content='0; url=https://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]'>";
              exit;
          }
          

          请注意,根据您的安装,您的服务器可能不支持 $_SERVER[SCRIPT_URI],但如果支持,这是更好的脚本。

          您可以在这里查看:Why do some PHP installations have $_SERVER['SCRIPT_URI'] and others not

          【讨论】:

            【解决方案10】:

            使用这个还不够:

            if($_SERVER["HTTPS"] != "on")
            {
                header("Location: https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
                exit();
            }
            

            如果您有任何 http 内容(如外部 http 图像源),浏览器将检测到可能的威胁。因此,请确保代码中的所有 ref 和 src 都是 https

            【讨论】:

              【解决方案11】:

              如果您使用支持 .htaccess 文件的 Apache 或类似 LiteSpeed 的软件,您可以执行以下操作。 如果您还没有 .htaccess 文件,您应该在根目录(通常是 index.php 所在的位置)中创建一个新的 .htaccess 文件。现在将这些行添加为 .htaccess 中的第一个重写规则:

              RewriteEngine On
              RewriteCond %{HTTPS} off
              RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
              

              对于所有重写规则,您只需要在 .htaccess 中使用一次“RewriteEngine On”指令,因此如果您已经拥有它,只需复制第二行和第三行即可。

              我希望这会有所帮助。

              【讨论】:

              • 这对我有用,也是我在类似 Zend 2 的框架上的自己的脚本中使用的 - 我不明白反对意见。
              • 也许您被否决了,因为答案与一年多前发布的@MatHatrik 中的this one 几乎相同?
              【解决方案12】:

              我用过这个脚本,它在网站上运行良好。

              if(empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == "off"){
                  $redirect = 'https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
                  enter code hereheader('HTTP/1.1 301 Moved Permanently');
                  header('Location: ' . $redirect);
                  exit();
              }
              

              【讨论】:

                【解决方案13】:

                我刚刚创建了一个 .htaccess 文件并添加了:

                RewriteEngine On
                RewriteCond %{HTTPS} off
                RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
                

                简单!

                【讨论】:

                  【解决方案14】:

                  在负载均衡器后面运行时必须做这样的事情。帽子提示https://stackoverflow.com/a/16076965/766172

                  function isSecure() {
                      return (
                          (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off')
                       || $_SERVER['SERVER_PORT'] == 443
                       || (
                              (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
                           || (!empty($_SERVER['HTTP_X_FORWARDED_SSL'])   && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on')
                          )
                      );
                  }
                  
                  function requireHTTPS() {
                      if (!isSecure()) {
                          header('Location: https://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'], TRUE, 301);
                          exit;
                      }
                  }
                  

                  【讨论】:

                    【解决方案15】:
                    <?php 
                    // Require https
                    if ($_SERVER['HTTPS'] != "on") {
                        $url = "https://". $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'];
                        header("Location: $url");
                        exit;
                    }
                    ?>
                    

                    就这么简单。

                    【讨论】:

                      【解决方案16】:

                      您应该强制 客户端 始终使用 HTTP Strict Transport Security (HSTS) 标头请求 HTTPS:

                      // Use HTTP Strict Transport Security to force client to use secure connections only
                      $use_sts = true;
                      
                      // iis sets HTTPS to 'off' for non-SSL requests
                      if ($use_sts && isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') {
                          header('Strict-Transport-Security: max-age=31536000');
                      } elseif ($use_sts) {
                          header('Location: https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'], true, 301);
                          // we are in cleartext at the moment, prevent further execution and output
                          die();
                      }
                      

                      请注意,大多数现代浏览器都支持 HSTS,但不是通用的。因此,如果用户最终使用 HTTP,上述逻辑会手动重定向用户而不考虑支持,然后设置 HSTS 标头,以便进一步的客户端请求应由浏览器重定向(如果可能)。

                      【讨论】:

                      • 我很惊讶没有其他答案包括这个标题,它非常重要......将它们两者结合起来有什么陷阱吗?
                      • 不...如果您始终想要 HTTPS,您绝对可以设置该标头。在进行重定向之前和之后设置它只是有点多余。我还修改了上面的回复,以更准确地解释兼容性。
                      • (编辑原始评论)我没有注意到“只有一页”的具体要求。 HSTS 将适用于所有页面;我的回答在技术上不正确。
                      • 仅供参考,标准 RFC 6797 第 7.2 节说“HSTS 主机不得在通过非安全传输传输的 HTTP 响应中包含 STS 标头字段。”所以当请求是普通的http时不需要发送,如果浏览器遵循标准则忽略。
                      • @mark 如果有 MITM 并且您的网站没有此标头,您可以允许包含的会话转到 http 并且人们输入他们的详细信息,他们可能不会注意到和重定向无济于事(中间的人将通过 https 连接到该站点并将其显示为 http)。使用此标头将在客户端强制使用 HTTPS。由于最近的 WPA2 WiFi 安全漏洞,这一点尤为重要。
                      【解决方案17】:

                      http://www.besthostratings.com/articles/force-ssl-htaccess.html

                      有时您可能需要确保用户正在通过安全连接浏览您的网站。可以使用包含以下行的 .htaccess 文件来实现始终将用户重定向到安全连接 (https://) 的简单方法:

                      RewriteEngine On 
                      RewriteCond %{SERVER_PORT} 80 
                      RewriteRule ^(.*)$ https://www.example.com/$1 [R,L]
                      

                      请注意,.htaccess 应位于网站主文件夹中。

                      如果您希望对可以使用的特定文件夹强制使用 HTTPS:

                      RewriteEngine On 
                      RewriteCond %{SERVER_PORT} 80 
                      RewriteCond %{REQUEST_URI} somefolder 
                      RewriteRule ^(.*)$ https://www.domain.com/somefolder/$1 [R,L]
                      

                      .htaccess 文件应该放在需要强制 HTTPS 的文件夹中。

                      【讨论】:

                        【解决方案18】:

                        使用$_SERVER['HTTPS'] 判断是否为SSL,如果不是则重定向到正确的位置。

                        请记住,显示表单的页面不需要通过 HTTPS 提供,最需要的是回发 URL。

                        编辑:是的,正如下面所指出的,最好在 HTTPS 中拥有整个过程。这更让人放心——我指出帖子是最关键的部分。此外,您需要注意将任何 cookie 设置为安全的,因此它们只会通过 SSL 发送。 mod_rewrite 解决方案也很漂亮,我用它来保护我自己网站上的很多应用程序。

                        【讨论】:

                        • 确实,表单本身不需要是 https,尽管对于大多数不知道这一点的人来说,这是一个好主意。如果他们即将提交表单并注意到锁图标不存在,他们可能会错误地认为表单不安全。
                        • @Graeme:此外,没有人可以肯定该表格将通过 https 发送。整个表单(通过 http 显示)可能是伪造的,提交到未知或 http 明文站点。 Https不仅仅是加密,它还对服务器进行身份验证。
                        【解决方案19】:

                        我之前做的方式基本上和你写的一样,但是没有任何硬编码的值:

                        if($_SERVER["HTTPS"] != "on")
                        {
                            header("位置:https://" . $_SERVER["HTTP_HOST"] . $_SERVER["REQUEST_URI"]);
                            出口();
                        }

                        【讨论】:

                        • 您忘记调用 exit() 以确保脚本在重定向后退出。我通常将它包装在一个名为 requireSSL() 的函数中。我可以在我想要加密的任何页面的顶部调用它。
                        • 将 if 更改为 (empty($_SERVER["HTTPS"]) || $_SERVER["HTTPS"] !== "on") 以修复 PHP 通知。
                        • $_SERVER[] 变量不是可变的/易受用户干预的影响吗?
                        • @ArianFaurtosh 来源?
                        • @ArianFaurtosh 有些是从客户端标头中提取的,例如 HTTP_X_FORWARDED,并且可以进行操作,但其他像 HTTPSSERVER_PORT 是直接从 Web 服务器设置的,通常应该 安全。
                        【解决方案20】:

                        您可以在 Apache 上使用指令和 mod_rewrite 来做到这一点:

                        <Location /buyCrap.php>
                        RewriteEngine On
                        RewriteCond %{HTTPS} off
                        RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
                        </Location>
                        

                        如果您愿意,您可以使用regular expressions 使位置变得更智能。

                        【讨论】:

                        • 你会把这个放在哪里? .htaccess 文件?
                        • REQUEST_URI 是否不包含“查询字符串”(如 ?page=1&id=41 等)?这就是apache文档所说的......所以如果我尝试访问site.com/index.php?page=1&id=12,我将被重定向site.com/index.php
                        • 来自 apache 文档:REQUEST_URI 请求的 URI 的路径组件,例如“/index.html”。这特别排除了作为其自己的变量 QUERY_STRING 可用的查询字符串。所以你需要在 REQUEST_URI 之后添加 QUERY_STRING
                        • 您还需要在其后添加 [R] 标志以使其重定向
                        【解决方案21】:

                        出于安全原因,您不应该这样做。特别是如果饼干在这里发挥作用。它让您对基于 cookie 的重放攻击敞开大门。

                        无论哪种方式,您都应该使用 Apache 控制规则来调整它。

                        然后您可以测试是否启用了 HTTPS,并根据需要在需要时重定向。

                        您应该只使用 FORM POST(不获取)重定向到支付页面, 并且对没有 POST 的页面的访问应该被引导回其他页面。 (这会抓住人们只是热跳。)

                        http://joseph.randomnetworks.com/archives/2004/07/22/redirect-to-ssl-using-apaches-htaccess/

                        是一个很好的起点,很抱歉没有提供更多。但你真的应该通过 SSL 推动一切。

                        这是过度保护,但至少你有更少的担忧。

                        【讨论】:

                          【解决方案22】:

                          不要在同一页面上混合使用 HTTP 和 HTTPS。如果您有一个通过 HTTP 提供的表单页面,我会在提交数据时感到紧张——如果不查看源代码并寻找它,我无法看到提交是通过 HTTPS 还是 HTTP。

                          通过 HTTPS 提供表单以及提交链接并没有太大的优势。

                          【讨论】:

                            猜你喜欢
                            • 2012-11-02
                            • 2015-02-09
                            • 1970-01-01
                            • 2019-11-21
                            • 1970-01-01
                            • 2012-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            相关资源
                            最近更新 更多