mxx*_*xxk 10 apache mod-rewrite url-rewriting
我已经定义了一对夫妇mod_rewrite
在一个规则.htaccess
文件,一个从重写URL路径/rwtest/source.html
来/rwtest/target.html
,而另一个禁止直接访问/rwtest/target.html
.也就是说,所有希望查看内容的用户都/rwtest/target.html
必须/rwtest/source.html
在其URL栏中输入.
我试图NS
在禁止规则中使用该标志以防止重写的URL被拒绝,但看起来这个标志不区分第一个请求和内部重定向.似乎NS
应该做这个工作,但我确信我误解了一些事情.
有人可以澄清这种行为吗?究竟是什么让这个内部重定向不是NS
标志可以忽略的内部子请求?
这是我的完整.htaccess
档案:
Options +FollowSymLinks -Multiviews
RewriteEngine on
RewriteBase /rwtest
# Forbid rule. Prohibit direct access to target.html. Note the NS flag.
RewriteRule ^target.html$ - [F,NS]
# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html
Run Code Online (Sandbox Code Playgroud)
我在Windows 7 x64上运行Apache 2.4.9,但我在Linux上观察到Apache 2.4.3上的类似行为.这是请求的日志输出/rwtest/source.html
.
[rewrite:trace3] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] strip per-dir prefix: C:/Apache24/htdocs/rwtest/source.html -> source.html
[rewrite:trace3] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] applying pattern '^target.html$' to uri 'source.html'
[rewrite:trace3] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] strip per-dir prefix: C:/Apache24/htdocs/rwtest/source.html -> source.html
[rewrite:trace3] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] applying pattern '^source.html$' to uri 'source.html'
[rewrite:trace2] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] rewrite 'source.html' -> 'target.html'
[rewrite:trace3] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] add per-dir prefix: target.html -> C:/Apache24/htdocs/rwtest/target.html
[rewrite:trace2] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] trying to replace prefix C:/Apache24/htdocs/rwtest/ with /rwtest
[rewrite:trace5] [rid#20b6200/initial] strip matching prefix: C:/Apache24/htdocs/rwtest/target.html -> target.html
[rewrite:trace4] [rid#20b6200/initial] add subst prefix: target.html -> /rwtest/target.html
[rewrite:trace1] [rid#20b6200/initial] [perdir C:/Apache24/htdocs/rwtest/] internal redirect with /rwtest/target.html [INTERNAL REDIRECT]
[rewrite:trace3] [rid#20ba360/initial/redir#1] [perdir C:/Apache24/htdocs/rwtest/] strip per-dir prefix: C:/Apache24/htdocs/rwtest/target.html -> target.html
[rewrite:trace3] [rid#20ba360/initial/redir#1] [perdir C:/Apache24/htdocs/rwtest/] applying pattern '^target.html$' to uri 'target.html'
[rewrite:trace2] [rid#20ba360/initial/redir#1] [perdir C:/Apache24/htdocs/rwtest/] forcing responsecode 403 for C:/Apache24/htdocs/rwtest/target.html
Run Code Online (Sandbox Code Playgroud)
我在下面发布了一些解决方法.
mxx*_*xxk 11
有几种解决方法,每种都有它们的优点和缺点.作为免责声明,我只是在.htaccess
上下文中测试它们.
添加RewriteCond
检查以查看是否%{ENV:REDIRECT_STATUS}
为空.如果为空,则当前请求不是内部重定向.
缺乏文件.自定义错误响应页面简要提到了此变量:
REDIRECT_
环境变量是从重定向之前存在的环境变量创建的.它们用REDIRECT_
前缀重命名,即HTTP_USER_AGENT
成为REDIRECT_HTTP_USER_AGENT
.REDIRECT_URL
,REDIRECT_STATUS
并且REDIRECT_QUERY_STRING
保证被设置,并且只有在错误条件之前存在其他标题时才设置其他标题.
我已经尝试了所有其他REDIRECT_
变量RewriteCond
,但除了REDIRECT_STATUS
内部重定向之外所有变量都是空的.为什么REDIRECT_STATUS
特殊的一个mod_rewrite
仍然是个谜.
# Forbid rule. Prohibit direct access to target.html.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^target.html$ - [F]
# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html
Run Code Online (Sandbox Code Playgroud)
此方法的学分转到URL重写:内部服务器错误.
与L
标志不同,END
即使对于内部重定向,也会暂停重写规则.
# Forbid rule. Prohibit direct access to target.html.
RewriteRule ^target.html$ - [F]
# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html [END]
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅END标志.
%{THE_REQUEST}
浏览器向服务器发送的完整HTTP请求行(例如,"GET /index.html HTTP/1.1").
THE_REQUEST
内部重定向不会更改,因此您可以匹配它.
比其他方法复杂得多.强制使用RewriteCond
只有一个RewriteRule
就足够的地方.
与大多数其他变量不同,匹配尚未转义(解码)的完整URL.
不方便在多个RewriteRule
s中使用.RewriteCond
s可以复制到每个上面,RewriteRule
或者可以将值导出到环境变量中(参见示例).两种黑客替代方案.
# Forbid rule. Prohibit direct access to target.html.
RewriteCond %{THE_REQUEST} "^[^ ]+ ([^ ?]*)" # extract path from request line
RewriteCond %1 ^/rwtest/target.html$
RewriteRule ^ - [F]
# Rewrite rule. Rewrite source.html to target.html.
RewriteRule ^source.html$ target.html
Run Code Online (Sandbox Code Playgroud)
或者,将路径导出到环境变量并在多个RewriteRule
s中使用它.
# Extract the original URL and save it to ORIG_URL.
RewriteCond %{THE_REQUEST} "^[^ ]+ ([^ ?]*)" # extract path from request line
RewriteRule ^ - [E=ORIG_URL:%1]
# Forbid rule. Prohibit direct access to target.html.
RewriteCond %{ENV:ORIG_URL} ^/rwtest/target.html$
RewriteRule ^ - [F]
# Rewrite rule. Rewrite source.html to target.html.
RewriteCond %{ENV:ORIG_URL} ^/rwtest/source.html$
RewriteRule ^ target.html
Run Code Online (Sandbox Code Playgroud)