从https切换到http时违反了RewriteRule


RewriteRule violates while switching from https to http

我在.htaccess文件中写了很多RewriteRule,但当我从https切换到http页面时会出现问题;它不遵循这些规则

注意:本地主机上一切正常,服务器上出现问题<----更新

这是我的网站,目前所有链接都按照重写规则*显示

例如关于我们页面链接显示为

http://www.mywebsite.com/about

但是

如果我在login page(在https上),并单击关于我们页面,则它会变成下面。

http://www.mywebsite.com/about?slug=about_us

或者,如果我点击左侧面板上的任何类别,它就会显示为

http://www.mywebsite.com/auction/category/1?cid=1

注意:即使鼠标悬停在页面上也会显示重写链接

以下是包含所需信息的.htaccess文件。

IndexIgnore *
RewriteEngine on
Options +FollowSymLinks 
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^auction/category/([0-9]+)/?$ bids.php?cid=$1 [NC]
RewriteRule ^login/?$ login.php [NC]
RewriteRule ^register/?$ register.php [NC]
RewriteRule ^logout/?$ logout.php [NC]
# static pages
RewriteRule ^about/?$ page.php?slug=about_us [NC]
# Rewrite to https
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} /login [OR]
RewriteCond %{REQUEST_URI} /do_login.php     
RewriteRule ^(.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,NC,L,QSA]
# don't do anything for images/css/js (leave protocol as is)
RewriteRule '.(gif|jpe?g|png|ico|css|js)$ - [NC,L]
# traffic to http:// except some pages
RewriteCond %{SERVER_PORT} ^443$ [OR]
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !(/login|/do_login.php)
RewriteRule ^(.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,NC,L,QSA]

注意:Here是完整的.htaccess文件

请告诉我哪里错了/失踪了?

我还有一些困惑

  • 如果我更改重写URL的大小写(Login或Login或Login),那么它会出错吗
  • 用所有RewriteRule编写[NC,L]是一种好的做法吗
  • 我应该在什么时候写[QSA]

更新

根据所有答案的建议,RewriteRule中的更改几乎解决了所有问题,但现在有最后一个问题。

  • /login的URL总是变为/login.php

下面是我更新的.htaccess

IndexIgnore *
Options -MultiViews
Options +FollowSymLinks
#mod_rewrite
RewriteEngine on
RewriteBase /
# Rewrite www to non www
RewriteCond %{HTTP_HOST} ^www.%{HTTP_HOST} [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}/$1 [R=301,L]
# minimize the css on all http:// pages
<IfModule mod_rewrite.c>
    RewriteCond %{HTTPS} off
   RewriteRule ^(.*).css$ /csszip.php?file=$1.css [L]
</IfModule>
#switch over http to https
# Rewrite to https
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} off
RewriteCond %{REQUEST_URI} (/login|/do_login)'.php [NC]
RewriteRule ^(.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# don't do anything for images/css/js (leave protocol as is)
RewriteRule '.(gif|jpe?g|png|ico|css|js)$ - [NC,L]
# traffic to http:// except some pages
RewriteCond %{SERVER_PORT} ^443$ [OR]
RewriteCond %{HTTPS} on
RewriteCond %{REQUEST_URI} !(/login|/do_login)'.php [NC]
RewriteRule ^(.*) http://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^login/?$ login.php [NC]
RewriteRule ^register/?$ register.php [NC]
# ...many other rules...with [NC] falg
RewriteRule ^auction/category/([^/.]+)/?$ bids.php?cid=$1 [NC]
RewriteRule ^about/?$ page.php?slug=about_us [NC]
# ...many more rules.... with [NC] flag

HTTPS建议

对于您的HTTPS问题,我会在端口或HTTPS上进行匹配,因为存在已知的与HTTPS标记相关的apache问题。

要在两者上覆盖此匹配(如您编辑的答案所示)

RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} != on
##REWRITE RULE
RewriteCond %{SERVER_PORT} ^443$ [OR]
RewriteCond %{HTTPS} = on
##REWRITE RULE

一个有效的观点是%{REQUEST_URI}不受任何取代的影响。

按照您目前的使用方式,如果有任何规则匹配,您将把它们发送到原始url(在任何替换开始之前)。

如果您想在和substation之后获取url并进行匹配,请使用$1


进一步问题的答案

如果我改变了重写URL的情况,那么它会出错吗

这是因为您的[NC]不在.htaccess HTTPS部分的重写条件下

如果你匹配RewriteCond %{REQUEST_URI} /login [OR],这只是在寻找小写登录,如果你想接受大写登录附加NC.


用所有重写规则编写[NC,L]是一种好的做法吗

不,这取决于你想做什么[NC]说这个规则上不匹配大小写,如果你不想在规则上匹配大小写(或条件),那么添加它。

案例与[NC]不匹配意味着site.com/login.php=sYte.com/login.HP

[L]意味着如果这是真的,停止处理所有


我应该在什么时候写[QSA]

QSA适用于您有?在您的替换中,并且您希望将旧字符串附加到新的URL

考虑以下规则:

RewriteRule /pages/(.+) /page.php?page=$1 [QSA]

使用[QSA]标志,对/pages/123?one=two的请求将被映射到/page.php?page=123&one=two。如果没有[QSA]标志,相同的请求将映射到/page.php?page=123,也就是说,现有的查询字符串将被丢弃

如果您想保留任何额外的get参数,请使用QSA。


另一个进一步的问题

/登录URL总是更改为/login.php

发生这种情况的唯一方法是,如果你在代码中的某个地方有一个重定向[R=301],我唯一能看到的地方就是这个部分:

# Rewrite to https
RewriteCond %{SERVER_PORT} !^443$ [OR]
RewriteCond %{HTTPS} != on
RewriteCond %{REQUEST_URI} (/login|/do_login)'.php [NC]
RewriteRule ^(.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]

只有与以下URL的匹配

.php、/login.php、/do_login.php

我相信罪魁祸首是我在%{REQUEST_URI} 的第一次响应中概述的

您的代码本质上说,如果满足这些条件,请将它们发送到https://theurltheywentto,这不是您想要做的,您希望将它们发送到/login。

你试过使用吗(如我在https部分所述)

RewriteRule ^(.*) https://%{HTTP_HOST}/login [R=301,L]

或者也许(如果你有/do_login)和其他选项

RewriteRule ^(.*).php https://%{HTTP_HOST}/$1 [R=301,L]

test.com/do_login.php的位置https://test.com/do_login

你试试吧:

# Rewrite to https
RewriteCond %{REQUEST_URI} (/login|/do_login)'.php [NC]
RewriteCond %{HTTPS} != on
RewriteRule ^(.*)'.php https://%{HTTP_HOST}/$1 [R=301,L]

我想这可能对有帮助

.htaccess将https重定向到不工作的http

对于最后一个问题,这可能对有帮助

http://httpd.apache.org/docs/current/rewrite/flags.html和

http://www.addedbytes.com/download/mod_rewrite-cheat-sheet-v2/png/

编辑:你可以尝试使用

RewriteCond %{SERVER_PORT} ^443$
RewriteCond %{SERVER_PORT} !^443$

而不是

RewriteCond %{HTTPS} on [NC]
RewriteCond %{HTTPS} off [NC] 

详细

请看这个链接,有人有类似的问题。请参阅后的第二次回复

http://www.webmasterworld.com/apache/3228459.htm

您可以通过创建域别名来解决此问题

您不能在.htaccess中执行此操作,但在http.conf <VirtualHost>部分中,您可以使用ServerNameServerAlias指令来完成此操作。

您对/关于的困惑是由于重定向到%{REQUEST_URI},在进行替换时不会更改。捕获URI,如果在这一轮重写处理过程中您并不真正想要URI,请使用$1。