第一部分
我在htaccess文件中(在OpehShift服务器上)有以下重写规则:
RewriteEngine on
# Must NOT be SSL
RewriteCond %{HTTP:X-Forwarded-Proto} =https
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d [or]
RewriteCond %{REQUEST_URI} /
RewriteCond %{REQUEST_URI} !^/user/login
RewriteCond %{REQUEST_URI} !^/user/register
RewriteCond %{REQUEST_URI} !^/user/profile
RewriteCond %{REQUEST_URI} !^/user/captcha
RewriteRule (.*) http://%{SERVER_NAME}/$1 [last,redirect=permanent]
# MUST be SSL
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/user/login [or]
RewriteCond %{REQUEST_URI} ^/user/register [or]
RewriteCond %{REQUEST_URI} ^/user/captcha [or]
RewriteCond %{REQUEST_URI} ^/user/profile
RewriteRule (.*) https://%{SERVER_NAME}/$1 [last]
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
目的是通过SSL处理一些路径,而其他所有路径都应通过普通的http访问。最初设置这样的配置是一个挑战,但最终解决了 - 你可以在OpenShift forums找到它的历史。
这在过去的某个时刻(可能是一些OpenShift更新)工作正常,当它开始在https页面上循环循环时:例如,当用户在他的个人资料页面上(使用https
)并点击链接时对于安全路径之外的页面,它会一次又一次地尝试重定向到https
。
根据规则,如果它不是登录,注册,个人资料或验证码页面,则应将https
更改为http
,但这不会再发生了。可能是什么问题?提前谢谢。
第二部分
尽管事实上我接受了@anubhava的答案(因为这似乎是Apache的问题不是我的问题,正如他在经过数小时的宝贵调试后所想的那样),我仍然在努力解决这个问题,而且任何进一步的解决方案/解决方案都是高度的欢迎。
同时将问题精确定位到以下代码:
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^(.*)$ - [env=ps:https]
RewriteCond %{HTTP:X-Forwarded-Proto} https
RewriteRule ^(.*)$ - [env=ps:http]
# known public pages
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^/site/page/about
RewriteRule (.*) %{ENV:ps}://%{SERVER_NAME}/$1?ps=%{ENV:ps}&step=1 [last,redirect=permanent]
现在当我转到about页面时,我得到了以下http标题:
HTTP/1.1 301 Moved Permanently
Date: Thu, 27 Nov 2014 15:07:27 GMT
Server: Apache/2.2.15 (Red Hat)
Location: https://mydomain.rhcloud.com/site/page/about?ps=http&step=1
Content-Length: 385
Content-Type: text/html; charset=iso-8859-1
Accept-Ranges: none
Keep-Alive: timeout=15, max=99
Connection: Keep-Alive
请注意,Location
有https
个原型,但ps
参数输出为http
(如预期的那样)。如果两个值都来自ps
变量,那怎么办?看起来很奇怪恕我直言。
简而言之:从https到http的重定向在OpenShift服务器上不起作用。尽管有规则说协议应该http
服务器发送https
- 因此循环重定向。
第三部分
也许我应该提到OpenShift网站使用HAProxy作为前端。它的配置不包含任何特定于ssl的设置。但是我找到了this related answer,其中有人可以读到:
最后,你没有能够实际将人们从HTTPS连接重定向,这被认为是不安全的,不受支持。
那么,对于从安全页面进行的重定向,HAProxy是否总是隐式覆盖https
的协议?那么如何解决这个问题?
答案 0 :(得分:1)
而不是REQUEST_URI
使用THE_REQUEST
,因为您正在使用前端控制器。
RewriteEngine on
# Must NOT be SSL
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{HTTP:X-Forwarded-Proto} =https
RewriteCond %{THE_REQUEST} !\s/+user/(login|register|profile|captcha) [NC]
RewriteRule ^ http://%{SERVER_NAME}%{REQUEST_URI} [L,R=301,NE]
# MUST be SSL
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteCond %{THE_REQUEST} \s/+user/(login|register|profile|captcha) [NC]
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [L,R=301,NE]
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
答案 1 :(得分:1)
最后我设法建立了一个解决方法,虽然我不认为它很优雅。如果您了解其他方式,请告诉我。我的意思是一种方式 - 在OpenShift环境中工作。
解决方案是使用.htaccess
仅处理单向重定向:从http
到https
。从https
到http
的重定向由客户端代码处理,该代码指示浏览器在不同方案下重新加载页面。
<强>的.htaccess 强>
RewriteEngine on
# MUST be SSL
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteCond %{THE_REQUEST} \s/+user/(login|register|profile|captcha)
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=302,NE]
# if a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# otherwise forward it to index.php
RewriteRule . index.php
<强>的index.php 强>
...
require('switchhttp.php');
...
<强> switchhttp.php 强>
<?
function redirect_url($url)
{
?>
<script>
window.location.href="<? echo $url; ?>";
</script>
<?
}
$urls = array("/user/login", "/user/register", "/user/captcha", "/user/profile");
$url = rawurldecode($_SERVER['REQUEST_URI']);
if(!in_array($url, $urls) && isset($_SERVER['HTTPS']))
{
redirect_url("http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]");
exit;
}
?>
这对我有用。
<子> 另外,我可能会警告那些可能感兴趣的人,OpenShift齿轮可能会意外地陷入缓存状态&#34;可以这么说(也许这与HAProxy特别相关)。在这种情况下,更新齿轮上的文件不会生效 - 您的浏览器,无论是否清除缓存,甚至绝对新连接的客户端都会收到旧页面。调试非常令人沮丧。到目前为止,我找到解决这个问题的唯一方法是重新启动你的装备。 子>