Search code examples
.htaccesserror-handlingcustom-error-pages

How to have two different custom error pages in .haccess?


1.

I have a .haccess file that requires you do be accessing from a certain IP address:

<RequireAll>
    Require ip XX.XX.XX.XX.XX YY.YY.YY.YY.YY ZZ.ZZ.ZZ.ZZ.ZZ
</RequireAll>

If someone tries to access the website from a IP other then X, Y, or Z then they get an error 403 Forbidden page. I have customized it using the following:

ErrorDocument 403 /.forbidden.php

2.

If someone tries to access a restricted file in the same directory (even if they are from ip addresses X, Y, or Z) then again they prompted with the SAME custom 403 Forbidden page.

My Question

How can I have two different custom 403 Forbidden pages based on why they are forbidden from accessing? In example 1 the forbidden page would /.wrongip.php and in example 2 the forbidden page would /.restricted.php


Solution

  • If this is about the extent of what you are doing then it is fine but if you are going to be doing a lot of redirecting I would consider doing this in PHP, but I digress. You are going to have to use Apache (2.4) module mod_rewrite to rewrite rules and conditions for the IP restriction portion. I would leave your custom 403 Forbidden as is for handling the other cases of that status code. If you are on shared hosting this module is usually enabled by most hosting providers by default.

    RewriteEngine On
    RewriteCond %{REMOTE_ADDR} !^111.222.333.444$
    RewriteRule ^(.*)$ /.wrongip.php [L]
    

    You will likely avoid confusion if you keep rule rewrites up near the top of your .htaccess file. You only need the RewriteEngine On line once in your file. RewriteCond is one of the conditions for the rule immediately following. You could have multiple conditions mapped to a single rule (using [OR] flag; AND behavior is by default).

    In this solution, the ^ character indicates the start of a string. Likewise, $ indicates the end. So, ^(.*)$ is a wildcard and would match any file accessed on your server. Preceded by a single space separator, the /.wrongip.php portion indicates your custom error page to be redirected to. [L] is the flag to indicate the Apache server should stop processing other rules once it matches that one. Use this unless you are using multiple rules to construct a single URL, otherwise you may cause yourself a headache.

    There is an additional flag, [R], that I would suggest being aware of and trying to use when possible for easier use in maintaining good practice with HTTP response codes. These help with search rankings and I would recommend specifying a 403 response because by default it will throw a 302 error which can negatively effect ranking over time. Changing the rule to RewriteRule ^(.*)$ /.wrongip.php [R=403,L] would cause the Apache server to issue an HTTP redirect to the browser (to /.wrongip.php) and communicate a 403 Forbidden error in the header. Since my example has all pages redirecting to /.wrongip.php for non-whitelisted IPs, most likely even /.wrongip.php itself, I think in your specific case the [R] flag would result in an HTTP redirect loop where they would keep requesting /.wrongip.php. In this case you should omit the [R] flag, this will cause the Apache server to do an internal redirect.

    Without the [R] flag, the client won't have any idea that this redirect went on (hence internal), so you should still emulate the error code in the header of your /.wrongip.php file using PHP.