使用.htaccess和mod_rewrite强制SSL / https

时间:2010-12-09 13:56:29

标签: php .htaccess mod-rewrite ssl https

如何使用PHP中特定的.htaccess和mod_rewrite页面强制使用SSL / https。

11 个答案:

答案 0 :(得分:412)

对于Apache,您可以使用mod_ssl强制使用SSLRequireSSL Directive

进行SSL
  

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

但这不会重定向到https。要重定向,请在.htaccess文件中使用mod_rewrite尝试以下内容

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

中给出的任何一种方法

如果您的提供商已禁用.htaccess,您也可以在PHP内部解决此问题(由于您提出要求,但这不太可能,但无论如何)

if (!isset($_SERVER['HTTPS']) || $_SERVER['HTTPS'] !== 'on') {
    if(!headers_sent()) {
        header("Status: 301 Moved Permanently");
        header(sprintf(
            'Location: https://%s%s',
            $_SERVER['HTTP_HOST'],
            $_SERVER['REQUEST_URI']
        ));
        exit();
    }
}

答案 1 :(得分:48)

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

如果您正在使用 CloudFlare,AWS Elastic Load Balancing,Heroku,OpenShift 或任何其他Cloud / PaaS解决方案,并且您正在体验具有正常HTTPS重定向的重定向循环,请尝试而是以下代码段。

RewriteEngine On

# If we receive a forwarded http request from a proxy...
RewriteCond %{HTTP:X-Forwarded-Proto} =http [OR]

# ...or just a plain old http request directly from the client
RewriteCond %{HTTP:X-Forwarded-Proto} =""
RewriteCond %{HTTPS} !=on

# Redirect to https version
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

答案 2 :(得分:35)

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

然后,在您希望强制通过PHP连接的这些页面的顶部附近,您可以require()包含此(和任何其他)自定义函数的集中文件,然后只需运行{{ 1}}功能。

HTACCESS / mod_rewrite解决方案

我没有亲自实现这种解决方案(我倾向于使用PHP解决方案,如上所述,因为它简单),但以下可能至少是一个良好的开端。

forceHTTPS()

答案 3 :(得分:8)

基于Mod-rewrite的解决方案:

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

RewriteEngine on

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

这会将您的非www www http请求重定向到 www 版本的https。

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

RewriteEngine on

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

这不适用于较低版本的apache,因为%{REQUEST_SCHEME}变量自2.4以来被添加到mod-rewrite。

答案 4 :(得分:7)

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

  • 默认情况下,只会执行最深的.htaccess文件中包含的规则。您必须指定RewriteOptions InheritDownBefore指令(或类似指令)才能更改此指令。 (see question)
  • 模式应用于相对于子目录的文件路径,而不是包含具有给定规则的.htaccess文件的上层目录。 (see discussion)

这意味着如果您在子目录中使用任何其他.htaccess文件,则Apache Wiki上建议的全局解决方案 not 无效。我写了一个修改后的版本:

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/

答案 5 :(得分:0)

此代码适用于我

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

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

没有其他答案对我有用。我的设置是带有经典ELB的AWS Beanstalk上的PHP应用程序。 .htaccess方法不起作用,因此我不得不将重定向规则应用于apache httpd.conf文件。例如。 (来自AWS文档):

Apache服务器:虚拟主机文件方法(推荐)

  1. 打开您的Apache配置文件。可能的位置包括/etc/httpd/conf/httpd.conf(Apache 2 / httpd),/ etc / apache2 / sites-enabled /(Apache 2.4)或/etc/apache2/apache2.conf(Ubuntu上的Apache)。 / p>

  2. 将重写规则添加到配置文件的VirtualHost部分,类似于以下内容。

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

  3. 保存您的Apache配置文件

  4. 重新启动Apache

请参阅此处: https://www.youtube.com/watch?v=hvqZV_50GlQ

https://aws.amazon.com/premiumsupport/knowledge-center/redirect-http-https-elb/

答案 8 :(得分:-1)

简单的一个:

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

将您的网址替换为example.com

答案 9 :(得分:-1)

只需使用Apache .htaccess强制SSL即可使用

SSLOptions +StrictRequire
SSLRequireSSL

重定向上面的答案是正确的

答案 10 :(得分:-1)

尝试此代码,它适用于所有版本的网址,例如

  • website.com
  • www.website.com
  • http://website.com
  • http://www.website.com

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