htaccess redirect 301 before other rules - apache

My htaccess look like this:
# Prevent directory listings
Options -Indexes
redirect 301 /old.html http://blablabla.pl/new
redirect 301 /other-page.html http://blablabla.pl/new-page
redirect 301 /xxx.html http://blablabla.pl/zzz
# Prevent visitors from viewing files directly
<FilesMatch "\.(sdb|md|html|txt)$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
</FilesMatch>
# URL rewrites
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(inc/|themes/|tmp/).*\.(php|html)$ - [F,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
</IfModule>
I'm using CMS that use html files as templates (there are variables, php code etc.). In htaccess of this CMS there are rules to prevent visitors from viewing html files directly. I moved one page to this CMS and wanted to do 301 redirect from old pages but it's not working - i'm getting 403 forbidden error. Is there a way to execute 301 redirect before other rules?

Working solution:
(...)
# Prevent visitors from viewing files directly
<FilesMatch "\.(sdb|md|html|txt)$">
<IfModule mod_authz_core.c>
Require all denied
</IfModule>
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
</FilesMatch>
<FilesMatch "(old\.html)|(other-page\.html)|(xxx\.html)">
Allow from all
Satisfy any
</FilesMatch>
(...)

Related

htaccess restrict access to index.php only

I was writing a .htaccess file for my PHP script.
This should only allow access to the index.php, cronjob.php and execute.php pages.
I wrote the .htaccess file as follows:
# Set default index file
DirectoryIndex index.php
# Disable indexing
Options -Indexes
# Set "403 Forbidden" as the default server behavior
Order Deny,Allow
Deny from all
# Allow requests to core PHP files
<FilesMatch "(index|execute|cronjob)\.php$">
Allow from all
</FilesMatch>
# If mod_rewrite module exists...
<IfModule mod_rewrite.c>
RewriteEngine On
# ...restrict access to PHP private directories
RewriteRule (^|/)logs(/|$) - [F]
RewriteRule (^|/)utils(/|$) - [F]
RewriteRule (^|/)modules(/|$) - [F]
</IfModule>
The main problem with this code is that https://example.com/ returns 403 Forbidden,
while https://example.com/index.php works.
You could put condition to check if a URI is NOT having either index.php OR cronjob.php or execute.php then forbid that page so else other pages will be forbid apart from these 3 php uris.
Please make sure you clear your browser cache before checking your URLs.
RewriteEngine ON
RewriteCond %{REQUEST_URI} !(index|cronjob|execute)\.php [NC]
RewriteRule ^ - [F]
In the end I managed to get it to work, I don't know if it's the best .htaccess possible, but this is what I ended up with:
# Set default index file
DirectoryIndex index.php
# Disable indexing
Options -Indexes
# Set "403 Forbidden" as the default server behavior
Order Deny,Allow
Deny from all
# Allow requests to core PHP files
<FilesMatch "^((index|execute|cronjob)\.php)?$"> # Basically, it accepts the three PHP files and the empty string.
Allow from all
</FilesMatch>

mod_rewrite root URLs for players AND website pages

I have player names working from the root directory something.com/username I also have an ID working to load a profile form ID instead something.com/id/1234, But I also want to be able to load my pages from index.php?page=about from something.com/about There are only about 6-10 pages, so I could create these manually in the htaccess.
I also need my search page to work with parameters something.com/search/searchterms
This is my current htaccess file.
# BEGIN Pretty Url's
Options -Indexes
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#Rewrite all urls to use slash at the end.
#RewriteRule ^(.*[^/])$ ./$1/ [L,R=301]
RewriteRule ^([_A-Z0-9a-z-+\.]+)/?$ ./pages/player.php?p=$1 [L]
RewriteRule ^id/([_0-9-+\.]+)/?$ ./pages/player.php?id=$1 [L]
# END Pretty Url's
# BEGIN Security Features
# Deny config.php
<files config.php>
order allow,deny
deny from all
</files>
# Deny all .hta* files
<files ~ "^.*\.([Hh][Tt][Aa])">
order allow,deny
deny from all
satisfy all
</files>
# Deny access to version file
<files inc/version.php>
order allow,deny
deny from all
satisfy all
</files>
# Deny access to security file
<files inc/security.php>
order allow,deny
deny from all
satisfy all
</files>
# END Security Features
Just add them all above the rules you already have:
RewriteEngine On
RewriteRule ^(about|page1|page2|etc)$ /index.php?page=$1 [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([_A-Z0-9a-z-+\.]+)/?$ ./pages/player.php?p=$1 [L]
RewriteRule ^id/([_0-9-+\.]+)/?$ ./pages/player.php?id=$1 [L]
Assuming the list of pages that you have is "about", "page1", "page2", and "etc". Note that doing something like this means you have have player names that are the same as your page names.

Apache - Deny access to all directories except public

I am developing a tool and I'm stuck at this point: I want to define a set of rules for each directory, basically I want only 'Public' folder avaible, and to deny access to other folders.
My directoy structure is
uapi(root)/
Application
Config
Public/
Index.php
Storage
.htaccess
and here is .htaccess file
<Directory /Public>
Order Deny, Allow
Allow from all
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ Index.php/$1 [L]
</IfModule>
</Directory>
<Directory /Config>
Order Deny, Allow
Deny from all
</Directory>
<Directory /Application>
Order Deny, Allow
Deny from all
</Directory>
<Directory /Storage>
Order Deny, Allow
Deny from all
</Directory>
As this doc page says, you cannot use the <Directory> directive inside htaccess, but only inside server conf files.
This is not a problem in your case anyway: you can store one .htaccess file inside each directory, eg. create these files:
Public/.htaccess
Order Deny, Allow
Allow from all
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ Index.php/$1 [L]
</IfModule>
/Config/.htaccess
Order Deny, Allow
Deny from all
/Application/.htaccess
Order Deny, Allow
Deny from all
/Storage/.htaccess
Order Deny, Allow
Deny from all
You can do all that using mod_rewrite itself from your main DOCUMENT_ROOT/.htaccess file. Use this code:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteRule ^(Application|Storage)(/.*|)$ - [NC,F]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^Public/(.*)$ /Public/Index.php/$1 [L,NC]
This code will throw Forbidden error for all the requests for /Storage/* or /Application/* but will let /Public/* be handled by /Public/index.php.
For Apache httpd server 2.4 you can do that in this way:
In httpd.conf or in a .conf file in httpd/conf.d/ dir.
<Directory "/uapi/">
Require all denied
</Directory>
<Directory "/uapi/public">
Require all granted
</Directory>
I tested this config. The reference is here.
You should be able to do this in .htaccess files too, if you don't have access to the Apache config files.
That would be, in /uapi/.htaccess:
Require all denied
and in /uapi/Public/.htaccess
Require all granted
As mentioned above, you can't use inside an .htaccess file. From Apache docs:
Note that unlike <Directory> and <Location> sections, <Files> sections can be used inside .htaccess files.
More general documentation:
https://httpd.apache.org/docs/2.4/howto/access.html

How to redirect all traffic to Apache document root

I have tinycms application and how could I forward all traffic to document root?
Example:
http://<IP-address>/ADFADSF/adsfadsf --> /
http://domain.com/adsf --> /
Currently, I have this in my .htaccess
<Files .htaccess>
order allow,deny
deny from all
</Files>
Options +FollowSymLinks
RewriteRule admin/$ index.php?view=admin [QSA]
Options -Indexes
Thanks.
James
Using mod_rewrite:
RewriteRule ^/?.+$ / [L,R]
Using mod_alias:
RedirectMatch ^/.+ /
This will,m of course, render the RewriteRule admin/$ index.php?view=admin [QSA] rule useless, or at the very least, cause some conflicts. So you should either comment that rule out, or create a special exception where all traffic except admin/ gets redirected.
EDIT:
How Im gonna do that to make an rule except admin/ ?
Here's one way to do it, I'm only guessing that this is the behavior you want. This stuff does not change, it's fine the way it is:
<Files .htaccess>
order allow,deny
deny from all
</Files>
Options +FollowSymLinks -Indexes
Add a:
RewriteEngine On
Then:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !^/(index\.php|admin)
RewriteRule ^/?.+$ / [L,R]
RewriteRule admin/$ index.php?view=admin [QSA,L]
So putting all that together, you have the deny for accessing .htaccess files. Then you have your Options, then your rewrite rules. You need to turn the RewriteEngine on, then redirect any request that isn't /index.php or /admin, then internally rewrite /admin to /index.php.

extra trailing slash mod-rewrite

I got a problem of the extra trailing slash that directs my website from
http://www.example.com/index to http://www.example.com//index
here's my .htaccess content
DirectoryIndex index.php
RewriteEngine On
RewriteBase /
# Apply rule to all web pages eg html, php, htm
# RewriteRule !\.(swf|zip|tar|tar|pdf|doc|txt|js|ico|gif|jpg|png|css|php)$ index.php [NC,L]
RewriteRule captcha.jpg com/actions/image.php
RewriteRule !(\.) index.php [NC,L]
#deny access to the .ht* files
order allow,deny
deny from all
#deny access to any *.ini files
order allow,deny
deny from all
#deny access to any *.log files
order allow,deny
deny from all
Get rid of the
RewriteBase /
By default, a .htaccess file in a directory will have a base path of / , so by adding another forward slash your overall rewrite base will be //