I have three different categories of URLs. Each category has a specific set of URLs I want to allow and everything else should be forbidden. This is to lock my site down.
These are the categories and the regular expressions I came up with. I'm using Apache 2.4.
First category:
http://example.org/foo
http://example.org/foo/bar
http://example.org/user
^/foo(/bar)?|user$
Second category:
http://example.org/baz/1?foo=bar
^/baz/[0-9]+\?foo=bar$
Third category:
http://example.org/search?bar=baz
^/search\?bar=baz$
Here are the rewrite rules I came up with based on the above:
RewriteEngine On
# Category 1
RewriteCond %{REQUEST_URI} !^/foo(/bar)?|user$ [NC]
RewriteRule ^(.*)$ - [F]
# Category 2
RewriteCond %{REQUEST_URI} !^/baz/[0-9]+$ [NC]
RewriteCond %{QUERY_STRING} !^foo=bar$
RewriteRule ^(.*)$ - [F]
# Category 3
RewriteCond %{REQUEST_URI} !^/search$ [NC]
RewriteCond %{QUERY_STRING} !^b=bar$
RewriteRule ^(.*)$ - [F,L]
The regular expressions look fine to me but as I was testing them at http://htaccess.madewithlove.be/, I noticed that the URL http://example.org/foo
will be forbidden at the expression for Category 2. I understand why this happens but I'm not sure how to resolve this. I might be missing something here, can someone tell me how I should fix this?
You should define the white list first, and then restrict/forbid everything else:
RewriteEngine On
RewriteRule ^(?:foo(?:/bar)?|user)/?$ - [L]
RewriteCond %{QUERY_STRING} ^foo=bar$
RewriteRule ^baz/\d+$ - [L]
RewriteCond %{QUERY_STRING} ^b=bar$
RewriteRule ^search$ - [L]
RewriteRule ^ - [F,L]