Forbid access to directory except only one subdirectory with .htaccess

.htaccessapache-2.4mod-rewrite

I have a following dir structure on file system:

/users/[uid1]/

/users/[uid2]/ etc. (UID part is dynamic in the url, like /users/abc123/ or /users/def456/)

Inside of uid-dirs I also have some subdirectories and files for example:
images-dir another-dir file1 file2

I also have a .htaccess file:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L,QSA]

So I rewrite every request to index.php for routing, only if requested file doesn't exist on file system.

Can I somehow forbid access to /users/[uid]/* except images-dir?

For example, allow:

/users/123abc/images-dir/some-image.jpg

and deny :

/users/123abc/another-dir

/users/123abc/file1

I need to deny direct access to this sub directories AND if somebody tries to get contents of forbidden files I want to send request to index.php

Is it possible to do with .htaccess?

Thanks

Best Answer

I assume you have a single .htaccess file in the document root.

You could do something like the following before your existing directives:

# If the request maps to a file or directory in the /users/<uid> space
# But is not the "images-dir" then forbid access
RewriteCond %{REQUEST_URI} !^/users/\w+/images-dir/
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^users/\w+/ - [F]

\w+ matches the <uid> and includes alphanumeric and underscore characters. If the <uid> follows a specific format then you could be more specific here.

If you only reference static resources in the /users/<uid>/... space (ie. no virtual URLs) then you could remove the above filesystem checks, since you know that every request targets a filesystem resource.