我正在托管一个节点应用程序,我的文件夹结构如下:
mydomain.com
--index.js
--package.json
--public\test.txt
我想将其public
视为我的文档根目录并且不允许访问其上方的任何内容,例如package.json
。
我目前正在使用.htaccess
来更改“文档根目录”:
RewriteCond %{REQUEST_URI} !public/
RewriteRule (.*) /public/$1 [L]
这工作正常,我可以访问http://example.com/test.txt
,但这也意味着http://example.com/public/test.txt
也可以工作。
如何防止public
直接在URL中使用而仅在后台使用?
我尝试添加RewriteRule ^public/ - [L,R=404]
到末尾,但最终所有内容都返回 404。
答案1
需要澄清的是,您实际上并没有在这里更改文档根目录,而是使用 URL 重写有效地隐藏了子目录。要实际更改文档根目录,您需要更改DocumentRoot
服务器配置中的指令(如评论中所述) - 这将产生其他影响(您的节点应用程序可能依赖于DocumentRoot
设置的)。
RewriteCond %{REQUEST_URI} !public/ RewriteRule (.*) /public/$1 [L]
检查是否存在“public/”任何地方在请求的 URL 路径中,这实际上不是您所需要的。但是,RewriteCond
此处不需要该指令。您应该检查 URL 路径中的RewriteRule
图案。 例如:
RewriteRule !^public/ /public%{REQUEST_URI} [L]
请注意,REQUEST_URI
服务器变量包含斜线前缀。(这也许就是为什么你删除了条件模式才能让它“工作”?)
我尝试添加
RewriteRule ^public/ - [L,R=404]
到末尾,但最终所有内容都返回 404。
这是正确的想法,然而,这本身也会改变重写URL(通过其他指令)。您只需定位直接请求。有几种方法可以做到这一点。我更喜欢检查REDIRECT_STATUS
环境变量,即空的最初设置为“200”,第一次成功重写后设置为“200”。例如:
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^public($|/) - [R=404]
($|/)
- 请注意,我还将尾部斜杠设为“可选”,因为它将匹配public
或public/
(使用交替) 访问裸目录时。这是为了避免 mod_dir 首先发出 301 重定向以在目录上附加尾部斜杠,然后再发送 404 以响应重定向的(第二个)请求。交替(字符串结尾或者斜线)确保public/<foo>
匹配,但public<foo>
如果您的 URL 以“public”开头(例如/public-enemy
),则不匹配。
使用非 3xx(或 2xx)状态代码时,无需该L
标志,因为它默示。
总之:
# Block direct requests to the "public" subdirectory
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^public($|/) - [R=404]
# Rewrite all requests that are not already for the "public" subdirectory
RewriteRule !^public/ /public%{REQUEST_URI} [L]
请注意,阻止(404)指令应该放在第一位。