如何用.htaccess拒绝直接请求文件但不影响RewriteRule正常转发?
解决直接访问image.php返回404但转发请求也被拦截的问题
你的规则逻辑存在漏洞:第一个RewriteRule将/image/xxx.jpg转发到/image.php?name=xxx后,Apache的重写引擎会继续对新生成的URL路径/image.php进行匹配,这时候第二个RewriteRule就会命中它,直接返回404,导致合法的转发请求也被误拦截。
要区分直接外部请求和内部重写转发的请求,你可以借助%{THE_REQUEST}变量——这个变量记录的是客户端发送的原始HTTP请求行,内部重写操作不会修改它。修改后的规则如下:
# 将/image/xxx.jpg转发到image.php处理 RewriteRule ^/image/([^/]+)\.jpg$ /image.php?name=$1 [L] # 仅拦截直接访问image.php的外部请求 RewriteCond %{THE_REQUEST} ^GET\ /image\.php RewriteRule ^/image\.php$ - [L,R=404]
规则说明:
- 第一个规则添加
[L]标记,让Apache处理完该规则后结束当前轮次的重写(内部转发后会进入下一轮,但后续条件会过滤掉合法请求) RewriteCond %{THE_REQUEST} ^GET\ /image\.php:仅当原始请求是直接访问image.php的GET请求时,才触发后续的404规则- 第二个规则的目标使用
-表示不修改URL,直接返回404状态码
验证效果:
- 直接访问
localhost/image.php:会命中RewriteCond和RewriteRule,返回404错误 - 访问
localhost/image/image.jpg:被内部转发到image.php,但原始请求行是GET /image/image.jpg HTTP/1.1,不满足RewriteCond的条件,因此不会被拦截,可正常处理
内容的提问来源于stack exchange,提问作者Jonathan Ivgi
相关产品推荐
相关产品推荐

