Deny ajax file access using htaccess

There are some scripts that I use only via ajax and I do not want the user to run these scripts directly from the browser. I use jQuery for making all ajax calls and I keep all of my ajax files in a folder named ajax.

So, I was hoping to create an htaccess file which checks for ajax request (HTTP_X_REQUESTED_WITH) and deny all other requests in that folder. (I know that http header can be faked but I can not think of a better solution). I tried this:

ReWriteCond %{HTTP_X_REQUESTED_WITH} ^$
ReWriteCond %{SERVER_URL} ^/ajax/.php$
ReWriteRule ^.*$ - [F]

But, it is not working. What I am doing wrong? Is there any other way to achieve similar results. (I do not want to check for the header in every script).


The Bad: Apache :-(

X-Requested-With in not a standard HTTP Header.

You can't read it in apache at all (neither by ReWriteCond %{HTTP_X_REQUESTED_WITH} nor by %{HTTP:X-Requested-With}), so its impossible to check it in .htaccess or same place. :-(

The Ugly: Script :-(

Its just accessible in the script (eg. php), but you said you don't want to include a php file in all of your scripts because of number of files.

The Good: auto_prepend_file :-)

  • But ... there's a simple trick to solve it :-)

auto_prepend_file specifies the name of a file that is automatically parsed before the main file. You can use it to include a "checker" script automatically.

So create a .htaccess in ajax folder

php_value auto_prepend_file check.php

and create check.php as you want:

<?
if( !@$_SERVER["HTTP_X_REQUESTED_WITH"] ){
        header('HTTP/1.1 403 Forbidden');
        exit;
}
?>

You can customize it as you want.


I'm assuming you have all your AJAX scripts in a directory ajax, because you refer to ^/ajax/.php$ in your non-working example.

In this folder /ajax/ place a .htaccess file with this content:

SetEnvIfNoCase X-Requested-With XMLHttpRequest ajax
Order Deny,Allow
Deny from all
Allow from env=ajax

What this does is deny any request without the XMLHttpRequest header.


There are only a few predefined HTTP_* variables mapping to HTTP headers that you can use in a RewriteCond. For any other HTTP headers, you need to use a %{HTTP:header} variable.

Just change

ReWriteCond %{HTTP_X_REQUESTED_WITH} ^$

To:

ReWriteCond %{HTTP:X-Requested-With} ^$