简体   繁体   English

如何使用htaccess(RewriteRule)重定向URL并防止直接访问

[英]How to redirect URL with htaccess (RewriteRule) and prevent direct access

using .htaccess I'd like to transparently redirect requests for folder "old" to folder "new", and in the same time prevent direct access to folder "new": 使用.htaccess,我想将文件夹“ old”的请求透明地重定向到文件夹“ new”,同时防止直接访问文件夹“ new”:

desired result: 预期结果:

http://example.com/old/ ... -> will display what's in "new" (no URL change in browser!) http://example.com/new/ ... -> no access http://example.com/old/ ...->将显示“新”中的内容(浏览器中没有URL更改!) http://example.com/new/ ...->无访问权限

this is my code in .htaccess (the 1st line is here because several domains share the same root folder): 这是我在.htaccess中的代码(第一行在这里,因为几个域共享同一根文件夹):

RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^old(.*)$ new$1 [L]
RewriteRule ^new(.*)$ - [F]

Well, what happens is that the 3d line triggers because of the substitution in the 2nd. 好吧,发生的是3d线由于第二个替换而触发。 I was convinced that the flag "L" would prevent this from happening (end of processing), but it seems that's not the case. 我确信标志“ L”将阻止这种情况的发生(处理结束),但是事实并非如此。

Do you have any suggestions what needs to be done (I tried to debug with rewrite log, but without success)? 您有什么建议需要做什么(我尝试使用重写日志进行调试,但没有成功)?

I did some logging and found the following: 我做了一些记录,发现以下内容:

[rid#d0ac98/initial] (3) [per-dir C:/www/example/] add path info postfix: C:/www/example/new -> C:/www/example/new/
[rid#d0ac98/initial] (3) [per-dir C:/www/example/] strip per-dir prefix: C:/www/example/new/ -> new/
[rid#d0ac98/initial] (3) [per-dir C:/www/example/] applying pattern '^new(.*)$' to uri 'new/'
[rid#d0ac98/initial] (4) RewriteCond: input='localhost' pattern='^example\.com$' => not-matched
[rid#d0ac98/initial] (4) RewriteCond: input='localhost' pattern='^localhost$' => matched
[rid#d0ac98/initial] (2) [per-dir C:/www/example/] rewrite new/ -> old/
[rid#d0ac98/initial] (3) [per-dir C:/www/example/] add per-dir prefix: old/ -> C:/www/example/old/
[rid#d0ac98/initial] (2) [per-dir C:/www/example/] strip document_root prefix: C:/www/example/old/ -> /example/old/
[rid#d0ac98/initial] (1) [per-dir C:/www/example/] internal redirect with /example/old/ [INTERNAL REDIRECT]
[rid#d217a8/initial/redir#1] (3) [per-dir C:/www/example/] strip per-dir prefix: C:/www/example/old/ -> old/
[rid#d217a8/initial/redir#1] (3) [per-dir C:/www/example/] applying pattern '^new(.*)$' to uri 'old/'
[rid#d217a8/initial/redir#1] (3) [per-dir C:/www/example/] strip per-dir prefix: C:/www/example/old/ -> old/
[rid#d217a8/initial/redir#1] (3) [per-dir C:/www/example/] applying pattern '^old(.*)$' to uri 'old/'
[rid#d217a8/initial/redir#1] (2) forcing 'C:/www/example/old/' to be forbidden

This seems an internal redirect, which causes the "forbidden" result. 这似乎是内部重定向,导致“禁止”结果。 Indeed, the documentation mentions it: 实际上,文档中提到了它:

It is therefore important, if you are using RewriteRule directives in one of these contexts, that you take explicit steps to avoid rules looping, and not count solely on the [L] flag to terminate execution of a series of rules, as shown below. 因此,重要的是,如果您在其中一种上下文中使用RewriteRule指令,则应采取显式步骤来避免规则循环,而不是仅仅依靠[L]标志来终止一系列规则的执行,如下所示。 An alternative flag, [END], can be used to terminate not only the current round of rewrite processing but prevent any subsequent rewrite processing from occurring in per-directory (htaccess) context. 替代标志[END]不仅可以用于终止当前的重写处理,而且还可以防止在每个目录(htaccess)上下文中发生任何后续的重写处理。 This does not apply to new requests resulting from external redirects... 这不适用于外部重定向导致的新请求...

So I suppose that in my example the error was due to the fact that I used "L" flag instead the "END" flag? 因此,我想在我的示例中,错误是由于我使用了“ L”标志而不是“ END”标志引起的?

I found an alternative solution (3rd line is inserted here): 我找到了替代解决方案(在此处插入了第三行):

RewriteCond %{HTTP_HOST} ^example\.com$ [NC]
RewriteRule ^old(.*)$ new$1 [L]
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^new(.*)$ - [F]

The 4th line will be executed only if there's no internal redirect. 仅当没有内部重定向时才会执行第四行。

You can use: 您可以使用:

RewriteEngine On

# if directly requesting /new then block it
RewriteCond %{THE_REQUEST} \s/+new(/\S*)?\s [NC]
RewriteRule ^ - [F]

# forward /old/abc to /new/abc
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteRule ^old(/.*)?$ new$1 [L,NC]

We used THE_REQUEST in first rule. 我们在第一条规则中使用了THE_REQUEST THE_REQUEST variable represents original request received by Apache from your browser and it doesn't get overwritten after execution of some rewrite rules . THE_REQUEST变量表示Apache从您的浏览器接收到的原始请求, 在执行某些重写规则后不会被覆盖 REQUEST_URI on the other hand changes its value after other rewrite rules. 另一方面, REQUEST_URI在其他重写规则之后更改其值。

For the same reason your rule RewriteRule ^new(.*)$ - [F] will even block your request from /old/ since first rule changes URI to /new/ . 出于同样的原因,由于第一个规则将URI更改为/new/因此您的规则RewriteRule ^new(.*)$ - [F]甚至会阻止您对/old/请求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM