.htaccess规则异常:部分真实目录存在时仍被错误跳转
.htaccess规则异常:真实存在的目录被错误重写
问题描述
配置的.htaccess规则如下:
Options +FollowSymLinks RewriteEngine On RewriteCond %{DOCUMENT_ROOT}/$1 !-d RewriteRule ^([0-9]+)(/)?$ index.php?page=$1 [QSA,L] RewriteRule ^([a-zA-Z-0-9]+)(/)?$ p/index.php?slug=$1 [QSA,L]
当前部分跳转符合预期:
- 数字路径如
https://website.com/2可正常跳转到https://website.com/index.php?page=2; - 不存在的目录路径如
https://website.com/UserString可跳转到https://website.com/p/index.php?slug=UserString; - 部分真实存在的目录如
./list、./blog访问时不会被跳转,符合规则设计。
但存在异常:服务器上真实存在的./reminders和./events目录,访问https://website.com/reminders/和https://website.com/events/时,被错误跳转到https://website.com/p/index.php?slug=reminders和https://website.com/p/index.php?slug=events。
原因分析
核心问题是**RewriteCond仅对紧跟在它后面的第一条RewriteRule生效**,第二条规则没有继承这个排除目录的判断条件。
当访问真实存在的目录(如reminders/)时:
- 第一条规则匹配数字路径,显然不匹配
reminders,直接跳过; - 第二条规则的模式
^([a-zA-Z-0-9]+)(/)?$会匹配目录名(包括末尾的斜杠),但此时没有检查该路径是否为真实目录,所以直接执行了重写。
至于./list、./blog未出现异常,大概率是这些目录下存在服务器默认的索引文件(如index.php、index.html),服务器优先返回索引文件内容,没有触发重写规则;而reminders、events目录可能没有默认索引文件,或者服务器配置不同,导致请求进入了重写流程。
解决方法
将排除目录的RewriteCond也应用到第二条RewriteRule上,修改后的.htaccess规则如下:
Options +FollowSymLinks RewriteEngine On # 处理数字路径:排除真实目录 RewriteCond %{DOCUMENT_ROOT}/$1 !-d RewriteRule ^([0-9]+)(/)?$ index.php?page=$1 [QSA,L] # 处理字符串路径:同样排除真实目录 RewriteCond %{DOCUMENT_ROOT}/$1 !-d RewriteRule ^([a-zA-Z-0-9]+)(/)?$ p/index.php?slug=$1 [QSA,L]
该修改直接确保两条规则都会跳过真实存在的目录,避免错误重写。
内容的提问来源于stack exchange,提问作者anothersanj
相关产品推荐
相关产品推荐

