.htaccess重写规则异常:密码重置Token URL访问报错排查
问题:Apache .htaccess重写规则导致Token URL解析失败
背景
我需要配置Apache的.htaccess重写规则,实现通过邮件发送带密码重置Token的URL供用户访问,但遇到了规则冲突问题。
初始.htaccess规则
Options +FollowSymLinks -MultiViews RewriteEngine On RewriteBase / RewriteCond %{HTTPS} off [OR] RewriteCond %{HTTP_HOST} ^www\.DOMAIN\.com [NC] RewriteRule ^(.*)$ https://DOMIAN.com/$1 [L,R=301] RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME}\.php -f RewriteRule ^(.*)$ $1.php [L] RewriteCond %{THE_REQUEST} ^(?:GET|POST)\ /.*\.php\ HTTP.*$ [NC] RewriteRule ^(.*)\.php$ $1 [R=301,L]
第一个问题:URL被重复添加.php后缀
当用户访问 example.com/activate/00803e6632236414ebcdc34c7e7690d764e567083fac6 时,URL被重复添加.php后缀,最终变为 example.com/activate/00803e6632236414ebcdc34c7e7690d764e567083fac6.php.php.php.php.php.php.php.php.php.php。
修改后的.htaccess规则
Options +FollowSymLinks -MultiViews RewriteEngine On RewriteBase / RewriteCond %{HTTPS} off [OR] RewriteCond %{HTTP_HOST} ^www\.EXAMPLE\.com [NC] RewriteRule ^(.*)$ https://EXAMPLE.com/$1 [L,R=301] RewriteCond %{THE_REQUEST} ^(?:GET|POST)\ /.*\.php\ HTTP.*$ [NC] RewriteRule ^(.*)\.php$ $1 [R=301,L] # Rewrite extensionless "\.php" URLs RewriteCond %{DOCUMENT_ROOT}/$1.php -f RewriteRule (.+) $1.php [L] # Rewrite "/<file>/<code>" to "/<file>.php/<code>" RewriteCond %{DOCUMENT_ROOT}/$1.php -f RewriteRule ^([^/]+)/([a-f0-9])$ $1.php/$2 [L]
新问题:文件不存在报错
修改后出现以下报错:
AH00128: File does not exist: /var/www/html/htdocs/activate/00803e6632236414ebcdc34c7e7690d764e567083fac6
解决方案
问题根源
- 初始规则中,
RewriteRule ^(.*)$ $1.php [L]的.*会匹配整个URL路径(包括Token部分),导致activate/xxx被重写为activate/xxx.php,后续规则循环执行不断添加后缀。 - 修改后的规则中,Token匹配正则
^([^/]+)/([a-f0-9])$仅匹配单个字符的Token,而实际Token是长字符串,规则不生效导致请求找不到文件。
修正后的.htaccess规则
Options +FollowSymLinks -MultiViews RewriteEngine On RewriteBase / # 强制HTTPS并移除www前缀 RewriteCond %{HTTPS} off [OR] RewriteCond %{HTTP_HOST} ^www\.EXAMPLE\.com [NC] RewriteRule ^(.*)$ https://EXAMPLE.com/$1 [L,R=301] # 隐藏.php后缀(外部访问时去掉.php) RewriteCond %{THE_REQUEST} ^(?:GET|POST)\ /.*\.php\ HTTP.*$ [NC] RewriteRule ^(.*)\.php$ $1 [R=301,L] # 优先处理带Token的路径:将/<file>/<token>重写为/<file>.php?token=<token> RewriteCond %{DOCUMENT_ROOT}/$1.php -f RewriteRule ^([^/]+)/([a-f0-9]+)$ $1.php?token=$2 [L] # 处理普通无后缀URL,对应到.php文件 RewriteCond %{DOCUMENT_ROOT}/$1.php -f RewriteRule ^([^/]+)$ $1.php [L]
说明
- 调整规则顺序:先处理带Token的特殊路径,避免被普通无后缀规则拦截。
- 修正Token匹配正则:
([a-f0-9]+)匹配任意长度的十六进制Token,符合示例格式。 - 将Token转为GET参数
token,activate.php可直接通过$_GET['token']获取;若脚本支持PATH_INFO,也可改为$1.php/$2,需确保PHP配置允许PATH_INFO。 - 普通无后缀规则限制为
[^/]+,仅匹配单级路径,避免干扰带Token的多级路径。
内容的提问来源于stack exchange,提问作者nw_prod
相关产品推荐
相关产品推荐

