如何将所有HTTP请求重定向到HTTPS


294

我正在尝试将网站(例如http://www.example.com)上的所有不安全的HTTP请求重定向到HTTPS(https://www.example.com)。我正在使用PHP btw。我可以在.htaccess中执行此操作吗?


1
您可以(并且应该)通过httpd而不是PHP来执行此操作。
德拉吉

2
@jnpcl,尽管我同意httpd解决方案比基于PHP的解决方案更好,但我认为一般而言,系统重定向不是一种好的做法。如果您想一直将用户重定向到HTTPS,请从“进入点”(指向您网站的第一个链接)将用户发送到该处,不要半途而废,否则可能会泄漏一些您认为是的数据受保护(如果您没有注意到即时重定向)。
布鲁诺

@Bruno:我一直在考虑重复的HTTP请求,丢失查询字符串的可能性以及用户手动输入的可能性http://
拖累了2010年

@jnpcl确实是个好点。我只是在建议,尽管人们倾向于要求这种重定向来提高其网站的安全性,但通常并不能真正改善它(因为它不会阻止同一请求首先通过纯HTTP)。 。
布鲁诺

8
@outis:您发布的第一个链接是这个问题。
2014年

Answers:


305

更新:尽管几年前已经接受了这个答案,但是请注意,Apache文档现在建议使用该方法。请Redirect改用。看到这个答案


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

24
就像我在回答/评论中说的,@ Cat,如果您尝试“将所有不安全的HTTP重定向到HTTPS”,则这种方法不会使这些请求变得安全,只会使浏览器使它们变得安全。两次,一次是不安全的,一次是安全的。
布鲁诺

13
您真正应该做的是与此同时使用HSTS
Reese Moore

3
这可能是我的apache版本(Centos 7中打包的2.4.6)中的错误,但这在某些URL上对我来说是个问题。例如,http://server/foo?email=someone%40example.com重定向到https://server/foo?email=someone%2540example.com即“ @”符号被URL引用两次。使用@ssc答案中的方法不会出现此问题。
psmears,2015年

2
错误的答案。它将仅重定向基本URL,而不重定向子文件夹中的URL。RewriteRule(。*)https://%{HTTP_HOST}%{REQUEST_URI} [R = 301,L]是正确的答案
FredTheWebGuy

7
他们不一定建议反对:In the case of the http-to-https redirection, the use of RewriteRule would be appropriate if you don't have access to the main server configuration file, and are obliged to perform this task in a .htaccess file instead.
亚当(Adam)

338

Apache的文档建议不要使用重写:

要将httpURL 重定向到https,请执行以下操作:

<VirtualHost *:80>
    ServerName www.example.com
    Redirect / https://www.example.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName www.example.com
    # ... SSL configuration goes here
</VirtualHost>

该段应进入主服务器配置文件,.htaccess如问的问题。

本文可能仅在提出问题并回答后才出现,但这似乎是当前的解决之道。


11
这应该是当前答案。但是,“ SSL配置”到底是什么?一个完整的例子将非常有帮助。
2014年

6
@Ben:这是一个不同的问题,该问题已在网上广泛记录;顺便说一句,我昨天刚刚添加了一个几乎完整的示例:serverfault.com/q/597012/26210,它可能使您了解SSL配置的内容
ssc 2014年

46
这是一个很好的提示。但是在Apache的文档中还提到:“在http到https重定向的情况下,如果您无权访问主服务器配置文件,并且必须在而是一个.htaccess文件。” 我的情况就是这样
peter_the_oak 2015年

4
@ user1844933如果使用permanent关键字,效果是相同的(浏览器收到301重定向)。例如:Redirect permanent "/" "https://example.com"
BeetleJuice

2
@Whitecat在Centos 6中,文件位于/etc/httpd/conf/httpd.conf
dstonek '18

141

我建议使用301重定向:

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

7
谢谢,这对我[L]
有用

1
是的 这是正确的答案,因为它也将所有URL都路由到了子文件夹中
FredTheWebGuy

这是htaccess文件的顶层吗?
CodyBugstein

1
@CodyBugstein就是我一直放置它的地方,它总是可以工作的。
大安范登伯格

3
所有答案都缺少一件事-如果您想将所有页面都重定向到https,则任何重定向代码都必须放在.htaccess文件的开头。
Vadim Anisimov '18

35

就像我在这个问题中所说的那样,我建议您避免盲目地将所有HTTP请求重定向到它们的等效HTTPS,因为这可能会给您带来错误的安全印象。相反,您可能应该将HTTP站点的“根”重定向到HTTPS站点的根并从那里链接,仅链接到HTTPS。

问题在于,如果HTTPS站点上的某些链接或表单使客户端将请求发送到HTTP站点,则在重定向之前,其内容将可见。

例如,如果您通过HTTPS投放的页面中有一个页面显示<form action="http://example.com/doSomething">并发送了一些不应该以明文形式发送的数据,则浏览器将首先将完整的请求(包括实体,如果是POST)发送到HTTP站点第一。重定向将立即发送到浏览器,并且由于大量用户禁用或忽略警告,因此很有可能被忽略。

当然,一旦提供某些侦听与HTTPS站点相同IP地址的HTTP端口上的内容,错误地提供了应该指向HTTPS站点但最终还是指向HTTP站点的链接可能会导致问题。但是,我认为将这两个站点保留为“镜像”只会增加犯错的机会,因为您可能会倾向于假设它会通过将用户重定向到HTTPS来自动更正自身,但这通常为时已晚。(在这个问题上有类似的讨论


1
在决定将整个站点作为HTTPS服务时,这种重定向是有意义的。我不希望用户获得403,因为他们为目标网页指定了http。我确实同意是否有人在链接中指定http并将其部署到性能不好的产品中。即使在进行重定向的情况下,也应在测试过程中将其捕获。我不喜欢“可能”的说法,因为这种“可能”在没有重定向的情况下发生。在安全浏览器进行测试时,除了确认后,在其重定向明确发送接收403,而不是症状是相同的
德里克·利兹

是的,如果有人错误地将http放在表单操作中,我会发现努力失败的好处,但是在大多数情况下,宽容键入的URL似乎更为重要。
Daniel Lubarov 2014年

4
@Daniel,我同意当用户键入URL时保持宽大很有用。我想说的是在开发/测试过程中最好禁用此功能,但在生产中(或在开发/测试的最后阶段)启用此功能的一种情况。
布鲁诺

为什么不在dns上将HTTP转换为https。
Muhammad Umer

1
@MuhammadUmer,因为这与DNS无关。它们通常使用相同的主机名,但是即使使用不同的主机名,您仍然需要更改协议和端口。
布鲁诺

18

我发现域名上https和www的最佳方法是

RewriteCond %{HTTPS} off 
RewriteCond %{HTTPS_HOST} !^www.example.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]

这不会重定向,http://www.example.com/...因为这两个条件是隐式与的。它们应该是“或”运算符,即。OR在第一个条件下包含标志(并记住在正则表达式中转义文字点)。但是,如果要实现HSTS,那么你不想重定向到HTTPS,并在单一的重定向WWW,你应该重定向到HTTPS 第一
怀特先生

我在哪里放这段文字?
亚伦弗兰克

关于类似类型的问题。任何人都可以帮助解决以下问题吗?stackoverflow.com/questions/59503217/...
appsntech

14

这是有效的html重定向方法,但不是最佳方法。

 <meta http-equiv="Refresh" content="0;URL=https://www.example.com" />

PHP方法

<?php
function redirectTohttps() {
    if ($_SERVER['HTTPS']!="on") {
        $redirect= "https://".$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
        header("Location:$redirect"); 
    } 
}
?>

.htaccess方法

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

复制自: www.letuslook.org


哪里.htaccess去了?而且,该链接已失效。
亚伦弗兰克

8

我喜欢这种从http重定向到https的方法。因为我不需要为每个站点进行编辑。

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

我在哪里放这段文字?
亚伦弗兰克

6

在您的.htaccess文件中使用以下代码会自动将访问者重定向到您网站的HTTPS版本:

RewriteEngine On

RewriteCond %{HTTPS} off

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

如果您有现有的.htaccess文件:

不要复制RewriteEngine On。

确保以RewriteCond和RewriteRule开头的行紧跟着已经存在的RewriteEngine On。


L和R是什么意思?
亚伦·弗兰克

5

根据GoDaddy.com,这是使用.htaccess将HTTP重定向到HTTPS的正确方法。代码的第一行是不言自明的。第二行代码检查是否关闭了HTTPS,如果是,它将通过运行第三行代码将HTTP重定向到HTTPS,否则将忽略第三行代码。

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

https://www.godaddy.com/help/redirect-http-to-https-automatically-8828


5

最佳解决方案取决于您的要求。这是先前发布的答案的摘要,并添加了一些上下文。

如果您使用Apache Web服务器并且可以更改其配置,请遵循Apache文档

<VirtualHost *:80>
    ServerName www.example.com
    Redirect "/" "https://www.example.com/"
</VirtualHost>

<VirtualHost *:443>
    ServerName www.example.com
    # ... SSL configuration goes here
</VirtualHost>

但是您也询问是否可以在.htaccess文件中执行此操作。在这种情况下,您可以使用Apache的RewriteEngine

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

如果一切正常,并且您希望浏览器记住此重定向,则可以通过将最后一行更改为以下内容来将其声明为永久重定向:

RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

但是如果您可能改变主意,请多加注意。浏览器会记住它很长时间,并且不会检查它是否已更改。

RewriteEngine On根据网络服务器的配置,您可能不需要第一行。

如果您要寻找PHP解决方案,请查看$ _SERVER数组标头函数

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

似乎Apache文档建议使用Rewrite路由。重定向怎么办?可以在去还有什么.htaccess文件?
亚伦·弗兰克

是的,重定向是首选,可以在.htaccess中使用。但是您不能添加条件以仅将HTTP流量重定向到https。它也重定向https->无限重定向循环。我在上面用于http(端口80)的VirtualHost指令中列出了它,.htaccess不支持该指令,因此在这里不能使用重定向。
麦凯尔'19

4

将以下代码添加到.htaccess文件中:

Options +SymLinksIfOwnerMatch
RewriteEngine On
RewriteCond %{SERVER_PORT} !=443
RewriteRule ^ https://[your domain name]%{REQUEST_URI} [R,L]

其中[您的域名]是您网站的域名。

您还可以通过将上面代码的最后一行替换为:从域名中重定向特定文件夹:

RewriteRule ^ https://[your domain name]/[directory name]%{REQUEST_URI} [R,L]

L和R是什么意思?
亚伦·弗兰克

4

请执行上面说明的所有重定向操作。只需在标题中添加“ HTTP Strict Transport Security”。这样可以避免人在中间攻击。

编辑您的apache配置文件(例如,/etc/apache2/sites-enabled/website.conf和/etc/apache2/httpd.conf),并将以下内容添加到VirtualHost中:

# Optionally load the headers module:
LoadModule headers_module modules/mod_headers.so

<VirtualHost 67.89.123.45:443>
    Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains; preload"
</VirtualHost>

https://zh.wikipedia.org/wiki/HTTP_Strict_Transport_Security


2

要将所有http请求重定向到https,您可以使用:

RewriteEngine on
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [NE,L,R]

如果未启用mod-rewrite且您使用的是Apache 2.4,则还可以使用Redirect内部if指令将http请求重定向到https

Apache 2.4。

<if "%{HTTPS} !~ /on/">
Redirect / https://www.example.com/
</if>

2

如果您无法直接访问站点的apache配置(许多托管平台仍以这种方式受到限制),那么我实际上建议采用两步方法。Apache自己记录的原因是,对于HTTP to HTTPS,首先应该在mod_rewrite上使用它们的配置选项。

首先,如上所述,您将设置.htaccess mod_rewrite规则:

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

然后,在您的PHP文件中(您需要在适合您情况的情况下进行此操作,某些网站将通过单个PHP文件收集所有请求,其他网站则根据其需求和发出的请求提供不同的页面):

<?php if ($_SERVER['HTTPS'] != 'on') { exit(1); } ?>

上面的代码需要在任何可能在不安全的环境中公开安全数据的代码之前运行。因此,您的站点通过HTACCESS和mod_rewrite使用自动重定向,而您的脚本可以确保在未通过HTTPS访问时不提供任何输出。

我想大多数人都不这么认为,因此Apache建议您在可能的情况下不要使用此方法。但是,它只需要在开发端进行额外检查,以确保您的用户数据是安全的。希望这可以帮助由于托管服务端限制而可能不得不考虑使用非推荐方法的其他人。


1

通过.htaccess这将有所帮助。

RewriteEngine On


RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ https://%1/$1 [R=301,L]

RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]

另外,请参阅此以获取更多详细信息。如何将Http重定向到Https?


1
对于任何遇到“重定向过多错误”并且无法更改allowOverride属性的人,这都是可行的解决方案。
Evochrome '17

1

除非您需要mod_rewrite做其他事情,否则使用Apache核心IF指令会更干净,更快捷:

<If "%{HTTPS} == 'off'">
Redirect permanent / https://yoursite.com/
</If>

您可以向IF指令添加更多条件,例如确保没有www前缀的单个规范域:

<If "req('Host') != 'myonetruesite.com' || %{HTTPS} == 'off'">
Redirect permanent / https://myonetruesite.com/
</If>

对所有内容都使用mod_rewrite有很多熟悉的惯性,但是请看这是否对您有用。

更多信息:https//httpd.apache.org/docs/2.4/mod/core.html#if

要查看它的运行情况(尝试不使用www。或https://,或使用.net代替.com):https : //nohodental.com/(我正在研究的网站)。



0

我找到了一种方法,可以强制将我的网站的所有页面从http重定向到对我有用的https上的页面模拟。

RewriteEngine On 
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

0
 Redirect 301 / https://example.com/

(当以上答案均无效时,为我工作)

奖金:

ServerAlias www.example.com example.com

(未找到固定的https:// www .example.com)


0

这会将所有URL重定向到https和www

RewriteCond %{HTTPS} off [OR]
RewriteCond %{HTTPS_HOST} !^www.example.com$ [NC,OR]
RewriteCond %{HTTP_HOST} !^www.example.com$ [NC]
RewriteRule ^(.*)$ https://www.example.com/$1 [L,R=301]

0

如果要从tomcat服务器执行此操作,请执行以下步骤

在独立的Apache Tomcat(8.5.x)HTTP Server中,如何配置它,以便如果用户键入www.domain.com,他们将被自动转发到https(www.domain.com)站点。

在[Tomcat_base] /conf/web.xml中的结束标记之前包含以下内容的2步骤方法

step 1: 
<security-constraint>
<web-resource-collection>
<web-resource-name>HTTPSOnly</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>

并设置[Tomcat_base] /conf/server.xml连接器设置:

step 2:
<Connector URIEncoding="utf-8" connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="443"/>
<Connector port="443" protocol="org.apache.coyote.http11.Http11NioProtocol"
maxThreads="150" SSLEnabled="true">
<SSLHostConfig>
<Certificate certificateKeystoreFile="[keystorelocation]" type="RSA" />
</SSLHostConfig>
</Connector>

注意:如果您已经进行了https配置并尝试重定向,请仅执行步骤1。



-1

此问题的另一个优势是负载均衡器开始发挥作用。

情况如下:-从浏览器到Load Balancer的往返流量(应该是HTTPS)-在Load Balancer和实际WebServer之间的流量为HTTP。

因此,PHP或Apache中的所有服务器请求变量都显示该连接只是HTTP。服务器上的HTTP和HTTPS目录是相同的。

批准答案中的RewriteCondition不起作用。它给出了一个循环,或者它根本不起作用。

问题是:如何使它在负载均衡器上工作。

(或者负载均衡器配置错误。这就是我希望的原因,因为这样我就可以将问题移至WebHosting公司:-))


重定向只需要在负载平衡器上进行即可。根据负载均衡器的类型,这应该可以在配置中实现,或者它本身是一个Apache实例,在此实例中可接受的答案将起作用。只是不要在单个节点上执行此操作。
marc82ch 2015年

-1

如果您使用的是接受HTTPS流量并将其通过http路由到服务器的Amazon Web Services Elastic Load Balancer,则在此处介绍正确的方法,将所有http流量重定向到https:https//aws.amazon。 com / premiumsupport / knowledge-center / redirect-http-https-elb

使用X-Forwarded-Proto标头(包含http或https),该标头始终包含在来自负载均衡器的http请求中,如下所述:https : //docs.aws.amazon.com/elasticloadbalancing/latest/classic/x- forwarded-headers.html

在httpd.conf文件中:

<VirtualHost *:80>

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule .* https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]

</VirtualHost>

或在您的根.htaccess文件中:

RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} =http
RewriteRule .* https://%{HTTP:Host}%{REQUEST_URI} [L,R=permanent]

奖励:它不会尝试重定向本地开发计算机上的http通信。


-1

这个对我有用:

<IfModule mod_rewrite.c>
 RewriteEngine On
  RewriteCond %{HTTPS} !on
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</IfModule>

例如,http:// server / foo?email = someone%40example.com正常重定向,不会出现任何问题。位于网站根文件夹中的文件.htaccess(例如,名为public_html)。可以使用 RewriteCond%{SERVER_PORT}!^ 443 $代替RewriteCond%{HTTPS}!on

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.