使用.htaccess和mod_rewrite强制SSL / https

我如何强制SSL / HTTPS使用.htaccess和mod_rewrite页面特定于PHP中。

对于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] 

或者在上面给出的任何不同的方法

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

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

PHP解决方案

从戈登的非常全面的答案直接借用,我注意到你的问题提到了强制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()一个包含此(和其他任何)自定义函数的集中文件,然后只需运行forceHTTPS()函数。

HTACCESS / mod_rewrite解决方案

我个人还没有实现过这样的解决方案(因为简单,我倾向于使用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] 

虽然Gordon的mod_rewrite解决方案对于您的普通Apache Web服务器正常工作,但我在代理服务器 (例如CloudFlare的站点或OpenShift) 之后遇到了重定向循环 。 以下解决方案适用于代理和非代理服务器:

 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] 

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

  • 只有最深的.htaccess文件中包含的规则将被默认执行。 你必须指定RewriteOptions InheritDownBefore指令(或类似的)来改变这个。 (见问题)
  • 该模式应用于相对于子目录的文件路径,而不是包含具有给定规则的.htaccess文件的上层目录。 (见讨论)

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

 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. # ie http://www.example.com/foo/ to https://www.example.com/foo/ 

基于Mod重写的解决方案:

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

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

这会将您的非wwwwww 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,因为自从2.4开始,%{REQUEST_SCHEME}变量被添加到mod-rewrite中。

这段代码适用于我

 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 

用example.com替换您的网址

只是用Apache .htaccess强制SSL,你可以使用

 SSLOptions +StrictRequire SSLRequireSSL 

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

试试这个代码,它将适用于所有版本的URLs