php 使用 .htaccess 和 mod_rewrite 强制 SSL/https

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4398951/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 12:56:09  来源:igfitidea点击:

Force SSL/https using .htaccess and mod_rewrite

php.htaccessmod-rewritesslhttps

提问by Sanjay Shah

How can I force to SSL/https using .htaccess and mod_rewrite page specific in PHP.

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

回答by Gordon

For Apache, you can use mod_sslto force SSL with the SSLRequireSSL Directive:

对于 Apache,您可以使用以下mod_ssl命令强制使用SSL SSLRequireSSL Directive

This directive forbids access unless HTTP over SSL (i.e. HTTPS) is enabled for the current connection. This is very handy inside the SSL-enabled virtual host or directories for defending against configuration errors that expose stuff that should be protected. When this directive is present all requests are denied which are not using SSL.

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

This will not do a redirect to https though. To redirect, try the following with mod_rewritein your .htaccess file

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

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

or any of the various approaches given at

或在给出的各种方法中的任何一种

You can also solve this from within PHP in case your provider has disabled .htaccess (which is unlikely since you asked for it, but anyway)

如果您的提供者禁用了 .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();
    }
}

回答by raphinesse

I found a mod_rewritesolution that works well for both proxied and unproxied servers.

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

If you are using CloudFlare, AWS Elastic Load Balancing, Heroku, OpenShiftor any other Cloud/PaaS solution and you are experiencing redirect loopswith normal HTTPS redirects, try the following snippet instead.

如果您正在使用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]

回答by Luke Stevenson

PHP Solution

PHP解决方案

Borrowing directly from Gordon's very comprehensive answer, I note that your question mentions being page-specific in forcing HTTPS/SSL connections.

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

Then, as close to the top of these pages which you want to force to connect via PHP, you can require()a centralised file containing this (and any other) custom functions, and then simply run the forceHTTPS()function.

然后,在靠近您要强制通过 PHP 连接的这些页面的顶部,您可以创建require()一个包含此(和任何其他)自定义函数的集中文件,然后只需运行该forceHTTPS()函数。

HTACCESS / mod_rewrite Solution

HTACCESS / mod_rewrite 解决方案

I have not implemented this kind of solution personally (I have tended to use the PHP solution, like the one above, for it's simplicity), but the following may be, at least, a good start.

我没有亲自实施这种解决方案(我倾向于使用 PHP 解决方案,就像上面的那样,因为它很简单),但以下可能至少是一个好的开始。

RewriteEngine on

# Check for POST Submission
RewriteCond %{REQUEST_METHOD} !^POST$

# Forcing HTTPS
RewriteCond %{HTTPS} !=on [OR]
RewriteCond %{SERVER_PORT} 80
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_secure [OR]
RewriteCond %{REQUEST_URI} ^something_else_secure
RewriteRule .* https://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

# Forcing HTTP
RewriteCond %{HTTPS} =on [OR]
RewriteCond %{SERVER_PORT} 443
# Pages to Apply
RewriteCond %{REQUEST_URI} ^something_public [OR]
RewriteCond %{REQUEST_URI} ^something_else_public
RewriteRule .* http://%{SERVER_NAME}%{REQUEST_URI} [R=301,L]

回答by starkeen

Mod-rewrite based solution :

基于 Mod 重写的解决方案:

Using the following code in htaccess automatically forwards all http requests to https.

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

RewriteEngine on

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

This will redirect your non-wwwand wwwhttp requests to wwwversion of https.

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

Another solution (Apache 2.4*)

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

RewriteEngine on

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

This doesn't work on lower versions of apache as %{REQUEST_SCHEME} variable was added to mod-rewrite since 2.4.

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

回答by lpd

I'd just like to point out that Apache has the worstinheritance rules when using multiple .htaccess files across directory depths. Two key pitfalls:

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

  • Only the rules contained in the deepest .htaccess file will be performed by default. You must specify the RewriteOptions InheritDownBeforedirective (or similar) to change this. (see question)
  • The pattern is applied to the file path relative to the subdirectory and not the upper directory containing the .htaccess file with the given rule. (see discussion)
  • 默认情况下,只会执行最深的 .htaccess 文件中包含的规则。您必须指定RewriteOptions InheritDownBefore指令(或类似指令)来更改它。(见问题)
  • 该模式应用于相对于子目录的文件路径,而不是包含具有给定规则的 .htaccess 文件的上层目录。(见讨论)

This means the suggested global solution on the Apache Wikidoes notwork if you use any other .htaccess files in subdirectories. I wrote a modified version that does:

这意味着对建议的全球性解决方案的Apache维基没有,如果你在子目录中使用任何其他的.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/

回答by Saurabh Mistry

Simple and Easy , just add following

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

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

回答by Alexufo

This code works for me

这段代码对我有用

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

回答by Sepehr Norouzi

Simple one :

简单一:

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

replace your url with example.com

用 example.com 替换您的网址

回答by webdesignwien

for just forcing SSL with Apache .htaccess you can use

仅使用 Apache .htaccess 强制使用 SSL,您可以使用

SSLOptions +StrictRequire
SSLRequireSSL

for redirect the above answer is correct

对于重定向上述答案是正确的

回答by Kashif Latif

try this code, it will work for all version of URLs like

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