Php 使用.htaccess和mod_重写强制SSL/https

Php 使用.htaccess和mod_重写强制SSL/https,php,.htaccess,mod-rewrite,ssl,https,Php,.htaccess,Mod Rewrite,Ssl,Https,如何使用.htaccess和mod_重写特定于PHP的页面强制SSL/https。对于Apache,您可以使用以下命令强制SSL: 此指令禁止访问,除非为当前连接启用了HTTP over SSL(即HTTPS)。这在启用SSL的虚拟主机或目录中非常方便,可以防止出现配置错误,从而暴露出应该保护的内容。当此指令存在时,所有不使用SSL的请求都将被拒绝 但这不会重定向到https。要重定向,请在.htaccess文件中尝试以下操作 RewriteEngine On RewriteCond %{HTT

如何使用.htaccess和mod_重写特定于PHP的页面强制SSL/https。

对于Apache,您可以使用以下命令强制SSL:

此指令禁止访问,除非为当前连接启用了HTTP over SSL(即HTTPS)。这在启用SSL的虚拟主机或目录中非常方便,可以防止出现配置错误,从而暴露出应该保护的内容。当此指令存在时,所有不使用SSL的请求都将被拒绝

但这不会重定向到https。要重定向,请在.htaccess文件中尝试以下操作

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

如果您的提供者禁用了.htaccess,您也可以从PHP中解决这个问题(这是不可能的,因为您要求它,但无论如何)

PHP解决方案 借用Gordon非常全面的回答,我注意到您的问题提到了强制HTTPS/SSL连接时的页面特定性

function forceHTTPS(){
  $httpsURL = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
  if( count( $_POST )>0 )
    die( 'Page should be accessed with HTTPS, but a POST Submission has been sent here. Adjust the form to point to '.$httpsURL );
  if( !isset( $_SERVER['HTTPS'] ) || $_SERVER['HTTPS']!=='on' ){
    if( !headers_sent() ){
      header( "Status: 301 Moved Permanently" );
      header( "Location: $httpsURL" );
      exit();
    }else{
      die( '<script type="javascript">document.location.href="'.$httpsURL.'";</script>' );
    }
  }
}

我找到了一个
mod_rewrite
解决方案,该解决方案适用于代理服务器和未代理服务器

如果您正在使用CloudFlare、AWS弹性负载平衡、Heroku、OpenShift或任何其他Cloud/PaaS解决方案,并且您遇到了正常HTTPS重定向的重定向循环,请尝试以下代码段

重新编写引擎打开
#如果我们收到来自代理的转发http请求。。。
RewriteCond%{HTTP:X-Forwarded-Proto}=HTTP[或]
#…或者只是直接从客户端发出的普通旧http请求
RewriteCond%{HTTP:X-Forwarded-Proto}=“”
重写cond%{HTTPS}=在…上
#重定向到https版本
重写规则^https://%{HTTP_HOST}%{REQUEST_URI}[L,R=301]

我只想指出,当跨目录深度使用多个.htaccess文件时,Apache的继承规则最差。两个关键陷阱:

  • 默认情况下,仅执行deep.htaccess文件中包含的规则。必须指定
    RewriteOptions-before
    指令(或类似指令)才能更改此设置
  • 该模式应用于相对于子目录的文件路径,而不是包含具有给定规则的.htaccess文件的上层目录
这意味着,如果在子目录中使用任何其他.htaccess文件,则上建议的全局解决方案将不起作用。我编写了一个修改版本,它可以:

RewriteEngine On
# This will enable the Rewrite capabilities

RewriteOptions InheritDownBefore
# This prevents the rule from being overrided by .htaccess files in subdirectories.

RewriteCond %{HTTPS} !=on
# This checks to make sure the connection is not already HTTPS

RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [QSA,R,L]
# This rule will redirect users from their original location, to the same location but using HTTPS.
# i.e.  http://www.example.com/foo/ to https://www.example.com/foo/
这个代码对我有用

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP:X-HTTPS} !1
RewriteRule ^(.*)$ https://%{HTTP_HOST}/$1 [R=301,L]
简单一点:

RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.example\.com)(:80)? [NC]
RewriteRule ^(.*) https://example.com/$1 [R=301,L]
order deny,allow

将您的url替换为example.com

基于Mod rewrite的解决方案:

在htaccess中使用以下代码会自动将所有http请求转发到https

RewriteEngine on

RewriteCond %{HTTPS}::%{HTTP_HOST} ^off::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]
这将把您的非wwwwwwhttp请求重定向到www版本的https

另一个解决方案(Apache 2.4*)


这在较低版本的apache上不起作用,因为自从2.4版以来,%{REQUEST_SCHEME}变量被添加到mod rewrite中。

试试这段代码,它将适用于所有版本的URL,如

  • 网站
  • www.website.com

简单易行,只需添加以下内容

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

出于好奇,为什么
RewriteCond%{REQUEST\u METHOD}^POST$
?因为POST参数不会保留在重定向上。如果你想确保所有的帖子提交都是安全的(任何不安全的帖子提交都将被忽略),你可以省略这一行。@Lucanos-如何编写一个重写条件,在发布时不强制重定向到http或https?My.htaccess在某些特定页面上强制使用HTTPS,然后在其余页面上强制使用HTTP。但是,在HTTPS页面上,有一些表单提交到我的web根目录。表单将操作url指定为HTTPS。但是,由于web根目录不是指定用于强制HTTPS的页面之一,因此my.htaccess会强制重定向,这意味着POST变量丢失。如何防止POST上的重定向?@StackOverdownEWBIE:行
RewriteCond%{REQUEST\u METHOD}^POST$
应该可以防止POST提交受到这些重定向的影响。我喜欢这个PHP版本。它更好,因为它考虑了一篇文章,如果已经发送了头,它的处理效果更好。这在我们的情况下非常好,因为我们目前混合了http和https流量。对于我们的管理区域,我们只是在保留站点其余部分http的同时弹出了.htaccess脚本。当我使用mod_rewrite方法时,我会被发送到https,但会出现“页面未正确重定向”错误。接下来:如果您遇到类似问题,请检查您的服务器和http变量。如果您的服务器使用代理,您可能希望使用
%{HTTP:X-Forwarded-Proto}
%{HTTP:X-Real-Port}
变量来检查SSL是否已打开。如果您在代理后运行的服务器(CloudFlare、Openshift)上遇到重定向循环,请参阅,以获得同样适用于这种情况的解决方案。@GTodorov-删除空格打破了我的重写规则。根据我对rewriterules(有限)的了解,语法是
RewriteRule
。因此,空间需要在那里,而单个
^
只是说“匹配所有输入URL”。这是非常棒的thx!但是否需要添加post条件?重写cond%{REQUEST_METHOD}^POST$@Aleksej True,这将中断未加密的POST请求。但我认为这是件好事。这样,人们就会注意到他们做错了什么。我想最好的办法是将他们重定向到一个页面,告知他们如何正确使用您的服务。@Raphinese您知道这个问题的答案吗:不!网站URL需要是动态的。这几乎是互联网上所有人告诉你的强制https的方法。然而,每次我这么做,我的整个网站都会被禁止,或者你没有查看的权限。像这样的事。。。我做错了什么?我只是想知道在我发布一个问题之前你是否有任何想法。我有一个类似的问题,我必须将规则应用到https.conf文件。见下面我的答案。
RewriteEngine on

RewriteCond %{HTTPS}::%{HTTP_HOST} ^off::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]
RewriteEngine on

RewriteCond %{REQUEST_SCHEME}::%{HTTP_HOST} ^http::(?:www\.)?(.+)$
RewriteRule ^ https://www.%1%{REQUEST_URI} [NE,L,R]
RewriteCond %{HTTPS} off
RewriteCond %{HTTPS_HOST} !^www.website.com$ [NC]
RewriteRule ^(.*)$ https://www.website.com/$1 [L,R=301]
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]