TransWikia.com

How can I limit .htaccess to current directory scope only?

Webmasters Asked by Kirikan on November 3, 2021

I have something like this:

Options -Indexes
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]
Order deny,allow
Deny from all
<FilesMatch "index.php|api.html|api_fetch.js">
  Allow from all
</FilesMatch>
<Directory /blog>
Allow from all
</Directory>
RewriteEngine off

The idea is to limit access in current directory (this one happen to be www-root) to whitelisted stuff and let .htaccess in any other directory, if there is one, do their own stuff. So this way, when I visit www.example.com/blog/, .htaccess generated by WordPress will do its work.

The problem is that .htaccess seems to be applying rules globally so my /blog/ gets the same restrictions.

How can I scope specific .htaccess per dir and let others do their job recursively starting from RewriteBase (i.e. WP’s RewriteBase /blog/ should continue recursively everywhere unless specific directory like wp-admin/ as its own .htaccess)?

One Answer

Use mod_rewrite to control access, instead of mod_authz_...

UPDATE: Because in .htaccess you simply don't have the fine grained control you require to limit access to a specific directory using the mod_authz_... directives. You would need access to the server config / VirtualHost. An inherent feature of .htaccess (directory context) is that it applies to the current directory and all subdirectories.

mod_rewrite is a powerful module that gives you the fine grained control you require. Since mod_rewrite is not inherited (by default), any mod_rewrite directives in subdirectories will naturally override directives in the parent - which would seem to be what you require.

Alternatively, you rethink your current directory structure and move the files that you want to protect into their own subdirectory - this is then trivial to "protect". Having a mixture of files you want to deny and allow access to in the current directory, whilst allowing all subdirectories is a bit of a code smell and inherently adds an additional layer of complexity.

Any mod_rewrite directives in subdirectories (eg. /blog/.htaccess) will naturally override this. In order to access other subdirectories you just need to make sure you only target the current directory.

For example:

Options -Indexes

RewriteEngine on

# Block all requests that target files in the current directory
# except for "index.php", "api.html" and "api_fetch.js"
# All virtual URLs are still allowed and passed through to the front-controller below
RewriteCond %{REQUEST_URI} !^/(index.php|api.html|api_fetch.js)$
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule ^[^/]+$ - [F]

# Front-controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?path=$1 [NC,L,QSA]

Aside: I realise this is pseudo-ish code, but...

:
<Directory /blog>
Allow from all
</Directory>
RewriteEngine off
  • The Allow, Deny and Order directives are deprecated on Apache 2.4 and should be replaced with the new Require (mod_authz_...) directives. These older directives have been moved to mod_access_compat and are provided for backwards compatibility only.

  • The <Director> container is not permitted in .htaccess, this can only be used in a server or virtualhost context.

  • The RewriteEngine off directive at the end of the file disables the rewrite engine for the entire file. (The last instance of this directives "wins".)

Answered by MrWhite on November 3, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP