如何强制用户通过 HTTPS 而不是 HTTP 访问我的页面?

我只有一个页面,我想强制访问作为一个 HTTPS 页面(PHP 在 Apache 上)。如何做到这一点,而不使整个目录需要 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');
}

但那不可能是正确的方法,对吧?

191901 次浏览

你可以在 Apache 上使用一个指令和 mod _ rewrite:

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

你可以使位置随着时间的推移更聪明地使用 正则表达式,如果你想要的。

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

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

编辑 : 是的,正如下面所指出的,最好将整个过程放在 HTTPS 中。这让人更加放心——我指出,这篇文章是最关键的部分。另外,您需要注意任何 cookie 都被设置为安全的,因此它们只能通过 SSL 发送。Mod _ rewrite 解决方案也非常漂亮,我在自己的网站上用它保护了很多应用程序。

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

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

不要把 HTTP 和 HTTPS 放在同一个页面上。如果你有一个表单页面是通过 HTTP 提供的,我会对提交数据感到紧张——如果没有查看源代码并搜索它,我就无法看到提交是通过 HTTPS 还是 HTTP 进行的。

通过 HTTPS 提供表单以及提交链接并不是一个重大的优势变化。

出于安全考虑,你不该这么做。尤其是在这里还有饼干的时候。它使您很容易受到基于 cookie 的重播攻击。

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

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

您应该只使用 FORM POST (no get)重定向到付费页面, 和访问网页没有一个 POST 应该直接回到其他网页。 (这将抓住人们只是热跳。)

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

是一个很好的开始,抱歉没有提供更多。但是您真的 应该推一切通过 SSL。

这是过度保护,但至少你少担心。

// 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);
}

您应该强制 客户请求 HTTPS 总是带有 HTTP严格传输安全(HSTS)头:

// 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 头,以便进一步的客户端请求应该被浏览器重定向(如果可能的话)。

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

有时您可能需要确保用户正在通过安全连接浏览您的站点。一种总是将用户重定向到安全连接(https://)的简单方法可以通过。Htaccess 文件包含以下行:

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 的文件夹中。

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

就这么简单。

在负载平衡器后面跑步时,不得不做这样的事情。帽子提示 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;
}
}

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

除非你拿它当诱饵。

$_ SERVER 传播可以根据知道如何修改的人的意愿进行修改。

同样,Sazzad Tushar Khan 和 thebigjc 说你也可以使用 httaccess 来做这件事,这里有很多答案包含它。

只要加上:

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

到你的.httaccess 的结尾,就是这样。

但是我们仍然不能像使用这两个工具那样安全。

剩下的就很简单了,如果缺少一些属性,比如..。

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

这里的一些堆栈-> < a href = “ https://stackoverflow. com/questions/4398951/Force-SSL-https-using-htaccess-and-mod-rewrite”> Force SSL/https using. htaccess and mod _ rewrite
还有
获取当前页面的完整 URL (PHP)
举几个例子。

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

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

很简单!

我已经使用这个脚本,它通过网站工作得很好。

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();
}

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

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

中只需要一次“ RewriteEngine On”指令。所有重写规则的 htaccess,所以如果你已经有了,只需要复制第二行和第三行。

希望这个能帮上忙。

仅仅使用这些是不够的:

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

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

我已经通过许多解决方案,检查的状态 $_ 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 ] ,但如果它支持,这是更好的脚本使用。

你可以在这里查询: 为什么一些 PHP 安装有 $_ SERVER [‘ SCRIPT _ URI’]而其他的没有

对于那些使用 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>

也许这个能帮上忙,你,这就是我为我的网站所做的,它像一个魔咒:

$protocol = $_SERVER["HTTP_CF_VISITOR"];


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

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 来做这件事,那么这种方法对我来说真的很有效:


<?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 superglobal 数组中的 HTTPS 变量,看它是否等于“ on”。如果变量不等于 on。

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

在.htaccess 文件中添加这些行

### Force HTTPS
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
if(location.protocol!=='https:'){location.replace(`https:${location.href.substring(location.protocol.length)}`);}