Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

mod_rewrite: allow redirect but prevent direct access

I am currently using mod_rewrite to do an internal redirection

RewriteCond  %{REQUEST_URI}  ^/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?

like image 439
Max Avatar asked Apr 24 '11 08:04

Max


3 Answers

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.

like image 172
CDuv Avatar answered Sep 20 '22 03:09

CDuv


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.

like image 25
Pekka Avatar answered Sep 24 '22 03:09

Pekka


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]
like image 44
AndrewR Avatar answered Sep 23 '22 03:09

AndrewR