对于Apache,您可以使用mod_ssl
和SSLRequireSSL指令
来强制启用SSL:
此指令禁止访问,除非当前连接启用了HTTP over SSL(即HTTPS)。在启用SSL的虚拟主机或目录中,这非常有用,可防止配置错误暴露应受保护的内容。当存在此指令时,所有未使用SSL的请求都将被拒绝。
但是,这不会重定向到https。要进行重定向,请尝试mod_rewrite
中的以下内容放入您的.htaccess文件中:
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();
}
}
我找到了一个mod_rewrite
的解决方案,适用于代理和非代理服务器。
如果您正在使用CloudFlare、AWS弹性负载均衡、Heroku、OpenShift或其他云/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]
直接借鉴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()
一个包含此(和任何其他)自定义函数的集中式文件,然后简单地运行forceHTTPS()
函数。
我个人没有实现过这种类型的解决方案(我倾向于使用像上面那样的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]
RewriteCond %{REQUEST_METHOD} !^POST$
? - depouloRewriteCond %{REQUEST_METHOD} !^POST$
这行代码应该可以防止 POST 请求受到重定向的影响。 - Luke Stevensonif (count( $_POST) > 0 || file_get_contents('php://input') )
- TheStoryCoder基于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请求重定向到https的www版本。
另一种解决方案(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中,因此这无法在低版本的Apache上运行。
我想指出的是,当使用多个不同深度目录下的.htaccess文件时,Apache拥有最差的继承规则。存在两个关键问题:
RewriteOptions InheritDownBefore
指令(或类似指令)才能更改此行为。(参见问题)这意味着如果您在子目录中使用其他.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.
# i.e. http://www.example.com/foo/ to https://www.example.com/foo/
简单易行,只需添加以下内容
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
这段代码对我有效
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
尝试使用这段代码,它适用于所有版本的URL:
RewriteCond %{HTTPS} off
RewriteCond %{HTTPS_HOST} !^www.website.com$ [NC]
RewriteRule ^(.*)$ https://www.website.com/$1 [L,R=301]
RewriteCond %{HTTPS} off
RewriteCond %{HTTPS_HOST} !^www.website.com$ [NC]
RewriteRule ^(.*)$ https://www.website.com/$1 [L,R=301]
mod_rewrite
解决方案。请参见https://dev59.com/H3M_5IYBdhLWcg3wjj4p#34065445/中的答案。 - raphinesse