如何用.htaccess将所有URI请求(含文件夹)重定向到index.php?
问题:.htaccess配置将所有URI(含文件夹)重定向到index.php失败
我的根目录结构如下:
- app
- admin
- public
- index.php
- .htaccess
我需要实现所有URI请求(包括与现有文件夹同名的请求)都重定向到index.php,当前情况:
www.example.com/anything→ 正常,已重定向到index.php,无HTTP错误www.example.com/admin→ 失败,返回HTTP 403 Forbidden(无权访问此资源)
其他请求均正常,只有访问与现有文件夹同名的URI时会出现禁止错误,请问如何修改配置,让所有请求都交由index.php处理?
当前的.htaccess配置:
<IfModule mod_rewrite.c> Options -MultiViews -Indexes +FollowSymLinks # 开启重写引擎 RewriteEngine On RewriteBase / # HTTP重定向到HTTPS RewriteCond %{HTTPS} !=on RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE] # 将请求重定向到index.php RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php/$1 [NC,L,QSA] # 拦截恶意查询字符串 RewriteCond %{QUERY_STRING} proc/self/environ [OR] RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR] RewriteCond %{QUERY_STRING} base64_encode.*(.*) [OR] RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR] RewriteCond %{QUERY_STRING} GLOBALS(=|[|\%[0-9A-Z]{0,2}) [OR] RewriteCond %{QUERY_STRING} _REQUEST(=|[|\%[0-9A-Z]{0,2}) # 将拦截到的请求返回403并指向index.php RewriteRule ^(.*)$ index.php [F,L] </IfModule>
更新:
按照建议移除了Options中的-Indexes以及目录条件RewriteCond %{REQUEST_FILENAME} !-d,但访问www.example.com/admin时出现ERR_TOO_MANY_REDIRECTS(重定向次数过多)错误。
修改后的.htaccess配置:
Options -MultiViews +FollowSymLinks # 将请求重定向到index.php RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php/$1 [NC,L,QSA]
解决方案
问题根源分析
- 原配置中
RewriteCond %{REQUEST_FILENAME} !-d规则会跳过对现有目录的重写,加上-Indexes禁止了目录索引,导致访问/admin时Apache找不到目录入口文件,直接返回403。 - 移除
!-d后出现循环,是因为重写后的index.php/admin会被Apache解析为index.php加路径信息,而规则没有排除index.php本身,导致反复匹配触发循环。
正确配置
<IfModule mod_rewrite.c> Options -MultiViews +FollowSymLinks # 开启重写引擎 RewriteEngine On RewriteBase / # HTTP重定向到HTTPS(无需可删除) RewriteCond %{HTTPS} !=on RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301,NE] # 直接放行index.php本身,避免循环 RewriteRule ^index.php$ - [L] # 重定向所有请求(含目录)到index.php,真实存在的文件直接访问(无需可删除!-f条件) RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php/$1 [NC,L,QSA] # 拦截恶意查询字符串 RewriteCond %{QUERY_STRING} proc/self/environ [OR] RewriteCond %{QUERY_STRING} mosConfig_[a-zA-Z_]{1,21}(=|\%3D) [OR] RewriteCond %{QUERY_STRING} base64_encode.*(.*) [OR] RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR] RewriteCond %{QUERY_STRING} GLOBALS(=|[|\%[0-9A-Z]{0,2}) [OR] RewriteCond %{QUERY_STRING} _REQUEST(=|[|\%[0-9A-Z]{0,2}) # 返回403并指向index.php RewriteRule ^(.*)$ index.php [F,L] </IfModule>
关键修改说明
RewriteRule ^index.php$ - [L]:直接放行index.php请求,彻底避免重写循环。- 保留
RewriteCond %{REQUEST_FILENAME} !-f:如果请求是真实存在的静态文件(如图片、CSS),直接访问不重写;若需要连静态文件也交由index.php处理,可删除此条件。 - 移除
-Indexes后,即使保留该选项,因目录请求已被重写,也不会再触发403错误。
内容的提问来源于stack exchange,提问作者Antonio Da Silva
相关产品推荐
相关产品推荐

