Trying to password protect a URL with htaccess - apache

I am using Expression Engine 2 Freelancer editon that doesn't have an authentication module.
I am trying to password protect a template group that has a virtual directory www.domain.com/template
What I am trying to do is use the htaccess in the root to force people to enter a username and password when they try and navigate to the to "template" section and the two files under it.
The way that Expression Engine works the templates are routed to and not physical directories.
My question is how can I password protect this url, I tried using LocationMatch but it didn't work?
Thanks

You can't efficiently protect a mod_rewritten URL (if it's possible at all). An attacker would just have to access the physical location that the protected URL gets rewritten to - which you would be leaving unprotected in this scenario.
You will still have to do this on PHP side, I think. If your PHP is running as an Apache module, it should be possible to check whether the requested resource belongs to the protected directory (either through QUERY_STRING or some other indicator), and then send the proper headers requesting authentication as described here in the PHP manual.

Which method of removing index.php from the URL are you using?
If you're using the "File and Directory Check" Method, you can modify the stock Apache mod_rewrite rule to exclude a certain directory while still allowing all other requests to be run thru index.php.
For example, using the base "File and Directory Check" rewrite rule:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
With this method, Apache checks to see if the file or directory exists -- if it does the file is served to the browser; if it doesn't exist then it's sent thru index.php and parsed as an ExpressionEngine URI.
To exclude your directory, modify the rewrite rule by adding your .htaccess Basic Authenticated password-protected directory:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !^/(secret-directory|secret-directory/.*)$
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
</IfModule>
I'm not fully aware of what all the limitations are with the Freelancer License, but I answered a similar question about password-protecting pages in ExpressionEnginethat may prove helpful in your situation.

Related

Why htaccess rules in subfolder stops parent htaccess rules from working? [duplicate]

been searching for 2 days and can't quite get the right solution due to my lack of understanding of mod_rewrite and time constraints on this project so hoping someone can help.
The aim
To rewrite all requests to the root index.php if the client doesn't have the correct cookie.
If the client has the correct cookie allow them to browse as they wish.
The problem
The htaccess in my subdirectory is taking precendence over my root htaccess, so requests such as www.mydomain.com/subdir/index.php arn't getting redirected.
My root .htaccess
Options FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_COOKIE} !^.*pass.*$
RewriteCond %{REQUEST_URI} !^/index.php$
RewriteRule ^(.*)$ http://www.mydomain.com/index.php?url=$0 [NC]
My subdir htaccess
RewriteEngine On
RewriteBase /
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php?/$1 [L]
Additional info
Ideally I'm trying to create a password protected area, so all requests are routed to index.php where a password can be entered and when verified a cookie is created, allowing free browsing of contents and sub directories. So if there is a better way to accomplish this then please let me know, and I havn't gone for .htpasswd since I need custom login, error and splash pages.
Also, the subdir .htaccess is an ExpressionEngine URL handler.
Thanks.
To allow execution of rewrite rules from parent .htaccess (htaccess from parent folder), you need to explicitly allow it (Apache will treat rewrite rules in current .htaccess as the only one that need to be executed, as long as rewritten URL remains in the same subfolder).
You need to add this line to your .htaccess in sub-folder:
RewriteOptions inherit
Apache manual: http://httpd.apache.org/docs/current/mod/mod_rewrite.html#rewriteoptions

How do I make a custom URL parser with Apache?

I heard this can be done with the web.config file. I want to make it so, for instance, my URL http://help.BHStudios.org/site might go to http://BHStudios.org/help.php?section=site, or http://i.BHStudios.org/u3Hiu might redirect to some other URL stored in a database with the hash u3Hiu as the key, or if something goes wrong and the internal file structure is exposed like http://Kyli.BHStudios.org/http/bhstudios/v2/self/index.php (something that happens with GoDaddy's servers for whatever reason) it'll change it to its intended URL http://Kyli.BHStudios.org before that's exposed tot he user.
Since I've never done this before, could you please also explain why you gave the answer you did?
A few Apache mod_rewrite rules in either your servers httpd.conf or in a .htaccess file, in your htdocs directory will do the majority of what you want e.g.
RewriteEngine On
RewriteBase /
# Default Rule - for non physical objects (not a file or directory):
# Internally rewrite (user won't see the URL) to /index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ /index.php [L]
#If the Browser request contains a .php, instruct the browser to remove it.
RewriteCond %{THE_REQUEST} \.php [NC]
RewriteRule ^/?(.*)\.php$ http://%{HTTP_HOST}/$1 [R=301,NC,L]
# Specific rule
RewriteRule ^/?site /help.php?section=site
The masking of real file system objects will not be perfect, and slightly pointless, as a user just needs to right click and view source on any served page, to obtain the actual URL's.

Apache rewrite rule to redirect all request to subdirectory containing another .htaccess and rewrite rules

I have public and private projects on my webserver. I put everything what is public into the webserver root, and I have a private folder there which I can only reach from local network (set by .htaccess in there).
I want to simply put every private projects in the private folder and handle the requests automatically, but want the URLs look like they are served from webroot.
For example if there is private/project1 I want to use the URL http://example.com/project1 to serve that folder and don't want to change the URL.
This simple rewrite:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ private/$1
works, but when I have a private/project2 with another .htaccess:
Options +FollowSymLinks
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /project2/
<Files .*>
Order Deny,Allow
Deny From All
</Files>
# Allow asset folders through
RewriteRule ^(assets/.+) - [L]
# Protect files from being viewed
RewriteRule ^(uploads.+) - [F,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]
</IfModule>
Options -Indexes
then the static content will appear, but the links are broken.
What should I modify to work ?
Also if I have a private/project3 and browse to http://example.com/project3/ there is no problem, but when I browse to http://example.com/project3 (without the trailing /) the URL will be visible as http://example.com/private/project3/ in the browser. Why ? How can I avoid that ?
All you need in your case is mod_alias.
Then serve your private project like:
Alias /project3 /apache/htdocs/private/project3
And with .htaccess you will control access rights.
If you want to control it without restarting server, you can try to achieve this with following config, that can be placed in .htaccess file:
RewriteRule ^/(project1)$ /private/$1/index.html
RewriteRule ^/(project1/)(.*)$ /private/$1$2
index.html - any index file for your project.
This way public part of URL's will be completly accessible, beside path's you are using for the private projects.
You also can add RewriteCond to check IP and enable rewriting only for your local network.
Actually, looking over your question it looks like this is an issue with mod_dir interferring with the path pipeline. Specifically, DirectorySlash which is by default turned on, will 301 redirect the browser when it thinks the browser is requesting a directory and is missing the trailing slash. You can try turning DirectorySlash Off but there's a security warning associated with it:
Turning off the trailing slash redirect may result in an information disclosure. Consider a situation where mod_autoindex is active (Options +Indexes) and DirectoryIndex is set to a valid resource (say, index.html) and there's no other special handler defined for that URL. In this case a request with a trailing slash would show the index.html file. But a request without trailing slash would list the directory contents.
That may or may not be applicable to your setup. You can also try modifying your rewrite rule to account for a trailing slash:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)/$ private/$1/
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ private/$1/
But I've had mixed results trying to get mod_rewrite and mod_dir to always play nicely with each other.
Wouldn't virtual domains be enough?
You could use a domain for private projects and another for public projects.
http://httpd.apache.org/docs/2.2/vhosts/examples.html

Redirect requests only if the file is not found?

I'm hoping there is a way to do this with mod_rewrite and Apache, but maybe there is another way to consider too.
On my site, I have directories set up for re-skinned versions of the site for clients. If the web root is /home/blah/www, a client directory would be /home/blah/www/clients/abc. When you access the client directory via a web browser, I want it to use any requested files in the client directory if they exist. Otherwise, I want it to use the file in the web root.
For example, let's say the client does not need their own index.html. Therefore, some code would determine that there is no index.html in /home/blah/www/clients/abc and will instead use the one in /home/blah/www. Keep in mind that I don't want to redirect the client to the web root at any time, I just want to use the web root's file with that name if the client directory has not specified its own copy. The web browser should still point to /clients/abc whether the file exists there or in the root. Likewise, if there is a request for news.html in the client directory and it does exist there, then just serve that file instead of the web root's news.html. The user's experience should be seamless.
I need this to work for requests on any filename. If I need to, for example, add a new line to .htaccess for every file I might want to redirect, it rather defeats the purpose as there is too much maintenance needed, and a good chance for errors given the large number of files.
In your examples, please indicate whether your code goes in the .htaccess file in the client directory, or the web root. Web root is preferred.
# If requested resource exists as a file or directory, skip next two rules
RewriteCond %{DOCUMENT_ROOT}/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/$1 -d
RewriteRule (.*) - [S=2]
#
# Requested resource does not exist, do rewrite if it exists in /archive
RewriteCond %{DOCUMENT_ROOT}/archive/$1 -f [OR]
RewriteCond %{DOCUMENT_ROOT}/archive/$1 -d
RewriteRule (.*) /archive/$1 [L]
#
# Else rewrite requests for non-existent resources to /index.php
RewriteRule (.*) /index.php?q=$1 [L]
From Rewrite if files do not exist
How about this?
# If requested resource exists as a file or directory go to it
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule (.*) - [L]
# Else rewrite requests for non-existent resources to /index.php
RewriteRule (.*) /index.php?q=$1 [L]
I seemed to have at least one problem with each of the examples above. %{DOCUMENT_ROOT} seemed to do the wrong thing in certain places, and some / characters seem to be missing. Here is my solution, which goes in the .htaccess in the web root.
Instead of using two rules (one for the case where the file under clients/ is found, and one for not found), all I need to check is if the requested file (or directory) does NOT exist. Because if it exists, no change is needed, it can just use the file provided in the client dir. Here's the code I settled on:
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}/clients/$1/$2 !-f
RewriteCond %{DOCUMENT_ROOT}/clients/$1/$2 !-d
RewriteRule ^clients/([^/]+)/(.*)$ $2 [L]
Thanks for your help!
RewriteCond %{REQUEST_FILENAME} !-f
Try this:
RewriteEngine on
RewriteRule ^clients/abc/ - [L]
RewriteCond %{DOCUMENT_ROOT}clients/abc/$0 -f
RewriteRule .* clients/abc/$0 [L]
I think you want something along these lines:
RewriteEngine on
RewriteCond %{DOCUMENT_ROOT}clients/$1/$2 -f
RewriteRule ^clients/([^/]+)/(.*)$ %{DOCUMENT_ROOT}clients/$1/$2 [L]
RewriteRule ^clients/([^/]+)/(.*)$ %{DOCUMENT_ROOT}$2 [L]

How would I go about creating a mod_rewrite that redirects to launch.php?i=/the/url/that/they/want?

So if the user types mydomain.com/dashboard, the document the server actually sends them is /launch.php?i=/dashboard.
The one caveat is that I would like to leave requests for
/flags
/people
/posters
/css
/icons
/images
/libraries
/patterns
alone, and they should request the actual folder.
How would I create such a mod_rewrite?
This is the .htaccess file for the CakePHP Framework.
Please replace the index.php and ?url= to fit your needs.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?url=$1 [QSA,L]
</IfModule>
The "!-d" tells Apache to follow existing folders and "!-f" to follow existing files.
Everything else is channelled through index.php
As suggested in a comment, you have to be aware that if it's not working it could be because mod_rewrite is not enabled and you'll not get an error stating that fact, you'll probably only have a HTTP 404.