Apache:从受限制的文件提供内容

在我的Apache安装程序中,我有一个包含我的错误页面的目录(404 403)。 但是,我不希望这个目录是直接可见的 – 我想访问它返回404。所以我做的是这样的:

# Use /hidden/404/ as the 404 page ErrorDocument 404 /hidden/404/ # Use /hidden/403/ as the 403 page ErrorDocument 403 /hidden/403/ <Directory /path/to/root/hidden/> # All requests return 404 RedirectMatch 404 .* </Directory> 

问题是在这种情况下,即使我明确告诉它(即处理404和403错误),Apache似乎也不愿意在这种情况下提供文件。 实际上,当我访问/hidden ,我收到以下消息:

 The requested URL /hidden/404/ was not found on this server. Additionally, a 404 Not Found error was encountered while trying to use an ErrorDocument to handle the request. 

任何方式我可以告诉Apache禁止访问目录,同时仍然允许自己在必要时提供这些文件?

好,我想出了一个办法。

我所做的就是使用mod_rewrite ,它是一个Apache模块(默认情况下提供所有安装),用于在运行中重写所请求的URL。 代码如下:

 # Custom error pages ErrorDocument 404 /hidden/404/index.html ErrorDocument 403 /hidden/403/index.html # Pretend that /hidden doesn't exist # (unless this is an internal redirect, # such as rendering a 404 or 403) RewriteCond %{ENV:REDIRECT_STATUS} ="" RewriteRule ^/hidden/.* - [L,R=404] 

那么让我们来看看这些线。 ErrorDocument指令没有改变 – 他们只是说当发生一个给定的错误时应该提供什么页面。

真正的肉是在RewriteCondRewriteRule指令。 RewriteRule指令说的是这样的:如果请求的path匹配正则expression式^/hidden/.* (本质上,任何在/ hidden /或其子树中的任何path),保持url不变(这就是-手段),但不要解释更多的RewriteRule指令(这就是L意思),并返回一个404错误代码(这就是R=404含义)。

这与ErrorDocument 404 /hidden/404/index.html指令相结合,似乎可以做到这一点。 然而问题是,当Apache去服务/hidden/404/index.html ,它再次贯穿这些规则。 这意味着RewriteRule指令被执行,反过来说,呈现404,整个事情只是无限循环。

因此,我们使用RewriteCond指令来确保这不会发生。 RewriteCond指令是条件 – 下面的RewriteRule指令只有在条件满足时才会被执行。 在这种情况下的条件是“环境variablesREDIRECT_STATUS等于空string”。 现在, REDIRECT_STATUS是一个由ErrorDocument设置的环境variables,并且保存着被redirect的状态码(所以,如果ErrorDocument 404 ...指令被触发,它将被设置为值“404”)。 但是,如果没有执行ErrorDocument指令,那么REDIRECT_STATUS将不会被设置,因此询问它的值将简单地返回空string。 因此, RewriteCond %{ENV:REDIRECT_STATUS} =""本质上是这样说的:“除非我们不在服务错误页面中间,否则不要在下面评估RewriteRule指令。


注意:如果你看过RewriteRule文档,你可能已经注意到R参数应该执行一个明确的redirect。 在这种情况下工作正常的原因是R参数有一个未公开的特性,它只能redirect300级代码。 因此, R=404不做明确的redirect,只有内部的一个。