使用.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]
这会将您的非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,因为自从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
- website.com
- http://www.website.com
- http://website.com
-
RewriteCond %{HTTPS} off RewriteCond %{HTTPS_HOST} !^www.website.com$ [NC] RewriteRule ^(.*)$ https://www.website.com/$1 [L,R=301]