Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/apache/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache 无法忽略带NS标志的mod_重写内部重定向_Apache_Mod Rewrite_Url Rewriting - Fatal编程技术网

Apache 无法忽略带NS标志的mod_重写内部重定向

Apache 无法忽略带NS标志的mod_重写内部重定向,apache,mod-rewrite,url-rewriting,Apache,Mod Rewrite,Url Rewriting,我在.htaccess文件中定义了两个mod_rewrite规则,一个用于将URL路径从/rwtest/source.html重写为/rwtest/target.html,另一个用于禁止直接访问/rwtest/target.html。也就是说,所有希望查看/rwtest/target.html内容的用户必须在其URL栏中输入/rwtest/source.html 我试图在禁止规则中使用NS标志来防止重写的URL也被拒绝,但是这个标志似乎没有区分第一个请求和内部重定向。似乎NS应该做这项工作,但我

我在
.htaccess
文件中定义了两个
mod_rewrite
规则,一个用于将URL路径从
/rwtest/source.html
重写为
/rwtest/target.html
,另一个用于禁止直接访问
/rwtest/target.html
。也就是说,所有希望查看
/rwtest/target.html
内容的用户必须在其URL栏中输入
/rwtest/source.html

我试图在禁止规则中使用
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
我在Windows7x64上运行Apache2.4.9,但在Linux上的Apache2.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
权变措施
我已经发布了一些解决方法。

这方面有几个解决方法,每个都有各自的优缺点。作为免责声明,我只在
.htaccess
上下文中测试了它们


解决方法1。检查是否存在空重定向\u状态 添加一个
RewriteCond
检查
%{ENV:REDIRECT_STATUS}
是否为空。如果为空,则当前请求不是内部重定向

赞成的意见
  • 确定内部重定向的最直接方法
欺骗
  • 缺乏文件。上的页面简要介绍了此变量:

    重定向
    环境变量是根据重定向之前存在的环境变量创建的。它们用
    REDIRECT\u
    前缀重命名,即
    HTTP\u USER\u AGENT
    变为
    REDIRECT\u HTTP\u USER\u AGENT
    <代码>重定向\u URL、
    重定向\u状态
    重定向\u查询\u字符串
    保证被设置,并且仅当其他标题在错误条件之前存在时才会被设置


    我尝试了
    RewriteCond
    中的所有其他
    REDIRECT\u
    变量,但是除了
    REDIRECT\u STATUS
    之外,所有变量都是空的,用于内部重定向。为什么
    REDIRECT\u STATUS
    mod\u rewrite
    中的一个特殊选项仍然是个谜

例子 此方法的学分将转到


解决办法2。停止重写规则处理,结束 与
L
标志不同,
END
即使对于内部重定向也会停止重写规则

赞成的意见
  • 简单。只是一个额外的旗帜
欺骗
  • 无法对要处理的规则和要跳过的规则进行足够的控制
例子 有关更多信息,请参阅


解决方法3。与_请求中的原始URL匹配
%{u请求}

浏览器发送到服务器的完整HTTP请求行(例如,“GET/index.html HTTP/1.1”)

请求不会随内部重定向而更改,因此您可以与之匹配

赞成的意见
  • 即使在第二轮URL处理中,也可以用于与原始URL进行匹配
欺骗
  • 比其他方法复杂得多。强制使用
    RewriteCond
    ,其中只有一条
    RewriteRule
    就足够了

  • 与大多数其他变量不同的是,匹配未取消扫描(解码)的完整URL

  • 在多个
    重写规则中使用不方便
    RewriteCond
    s可以复制到每个
    RewriteRule
    的上方,或者可以将值导出到环境变量(参见示例)。这两种方法都很老套

例子 或者,将路径导出到环境变量,并在多个
重写规则中使用它

# 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

谢谢你这么完整的回答。解决了我的问题!另一个带有
END
标志的“con”。。。它是Apache2.4+。检查
请求一直是我选择的“变通方法”。“我在
RewriteCond
中尝试了所有其他
重定向
变量,但是除了
重定向状态
之外,所有变量对于内部重定向都是空的。”-是的,我看到了相同的行为。在Apache 2.2文档中,它们被描述为“类似CGI的环境变量”,虽然它们似乎不可用于mod_重写,但它们可以在您的CGI/服务器端脚本中使用(并且对于错误文档非常有用,这似乎是Apache文档中唯一讨论它们的地方)。“有人能澄清一下这种行为吗?”-是的,内部重写不是子请求。(您还可以检查
IS_SUBREQ
服务器变量,对于内部重写,该变量保持
为“false”
)。其他模块触发子请求,例如mod_dir和mod_include(SSI)。
# 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]
# 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
# 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