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
精彩评论