开发者

mod_rewrite: allow redirect but prevent direct access

I am currently using mod_rewrite to do an internal redirection

RewriteCond  %{REQUEST_URI} 开发者_Go百科 ^/pattern$
RewriteRUle .* file.php

However I would like to prevent direct access to file.php by redirecting requests to that file to a page not found URL.

RewriteCond %{REQUEST_URI} /file.php
RewriteRule .* page-not-found.php

The problem is that the second rule also applies when I do the first redirect and therefore breaks my first internal redirect.

[Q] Is there a way to allow the first redirect but prevent direct access to the redirected file?


Using ENV:REDIRECT_STATUS variable (see mromaine's contribution to "Hidden features of mod_rewrite" community wiki:

RewriteCond  %{REQUEST_URI}  ^/pattern$
RewriteRule .* file.php

# Redirect direct access to file.php
RewriteCond %{REQUEST_URI} /file.php
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule .* page-not-found.php

Test cases:

  • http://example.com request gets server's index file (index.htm, index.php, etc.)
  • http://example.com/somefile.htm request gets somefile.htm
  • http://example.com/somedir request gets somedir's index file
  • http://example.com/pattern request gets file.php file
  • http://example.com/file.php request gets page-not-found.php file

Every HTTP responses are HTTP 200.


Edit: Inspired by @AndrewR's answer (which in its current form however didn't seem to work for me - it looks like the second rule gets applied anyway.) a .htaccess only solution that works with a secret key.

If you encounter a valid pattern, add a secret key to the query string.

Then test for that secret key when deciding upon the page redirect.

RewriteEngine on
Options +FollowSymlinks

RewriteCond  %{REQUEST_URI}  ^/pattern$
RewriteRule .* /file.php?SUPER_SEKRIT_KEY [QSA]

RewriteCond %{QUERY_STRING} !SUPER_SEKRIT_KEY
RewriteCond %{REQUEST_URI} /file.php
RewriteRule .* /test/page-not-found.php [L,F]

Use a more complex key of course, and for internal redirects only! Otherwise, the user will be able to grab the secret key.


You can add a [L] at the end of the rewrite rule, which signifies Last, or no more processing. This will only work inside the Apache config. It does not work in an .htaccess file.

RewriteEngine On

RewriteCond  %{REQUEST_URI}  pattern$
RewriteRule .* /file.php [L]

RewriteCond %{REQUEST_URI} file.php$
RewriteRule .* /page-not-found.php [L]


A simpler way to do this only using .htaccess.

Move your file.php into a new directory called securedir. In the root directory use this .htaccess file.

RewriteEngine On
RewriteRule ^pattern$ securedir/file.php

Prevent access to anything in securedir with this in an .htaccess file there. (Or direct them back to a different page if you prefer.)

deny from all
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜