3

I ran into the following issue:

On a website I want to prevent "unauthorized" access to a set of .xml files - the user has to authenticate first. Now it would be possible for an authenticated user to type the URL of the file I don't want them to see. To prevent this, I created a simple php script that checks user authentication, then serves up the XML (with appropriate Content-type header).

At the same time, I put the following in the .htaccess file in the directory with .xml (and other) files:

<Files ~ "(.xml)">
Order allow,deny
Deny from all
Allow from xx.yy.zz.tt (IP address of server)
</Files>

This did the trick - .xml files were not longer "directly accessible", even for an "authenticated" user. But here is the thing I don't understand:

If I leave out the 'Allow from' line, the php script still manages to access the .xml files. It seems that the .htaccess is completely ignored when it comes to php.

So my question is two fold:

  1. Is this expected behavior?
  2. If so, then what method would one use to prevent a php script from accessing a particular file (or group of files)?

There is clearly a fundamental issue around .htaccess that I completely failed to grasp. Thanks for your insights.

2 Answers 2

3

PHP doesn't work with the file over HTTP but directly on the filesystem, unless you access the file over HTTP using cUrl or file_get_contents('http://.../file.xml').

If you want to prevent the files from being accessed without the user being authenticated first, place the files outside the public directory and serve them from there.

/files/
/public_html/index.php

Now, for the files...

if ($user->isAuthenticated()) {
    // set proper file header
    // print out the file content from /files/
}

Documentation might help you get a grasp on what I have in mind... https://www.php.net/manual/en/function.readfile.php#48683

This way you'll prevent anonymous users from accessing the files as those are not stored in a publicly accessible directory.

3
  • Interesting - what you are saying is that the way that php asks for the file with file_get_contents() depends on whether http:// is included, or whether it asks directly for the file. That makes sense and explains the behavior I'm seeing. I will leave this open for another day to see if any other answers come along - otherwise I will accept this one as "close enough". Thanks.
    – Floris
    Apr 13, 2014 at 21:53
  • 2
    +1 spot on. @Floris Whether file_get_contents() works at all with HTTP:// is dependent on the relevant protocol wrapper being installed and allow_url_fopen being enabled. In which case the behaviour of PHP when requesting the URL http://... is entirely different from requesting the local file. PHP makes an external HTTP request for the resource - in the same way your browser makes a request - in this case your Allow from xx.yy.zz.tt line would be required. Another way of looking at it is that by the time your PHP script executes, the .htaccess file has already been processed.
    – MrWhite
    Apr 13, 2014 at 22:27
  • @w3d thank you for the further clarification. Your last point makes things very clear.
    – Floris
    Apr 14, 2014 at 0:29
0

The .htaccess file is meant to be used by the HTTP Server, not PHP. Yet, you can setup PHP to read and adhere to the rules of the .htaccess file, if you need to do as such.

3
  • "setup PHP to ... adhere to the ... .htaccess file" - How do you do this? Manually parse the file? I imagine this would be error prone if the .htaccess file has any complexity. My gut feeling is that this is unnecessary and should be avoided.
    – MrWhite
    Apr 14, 2014 at 7:32
  • Thanks for responding. Could you clarify how you would set up php to adhere to the rules of .htaccess? Are you suggestion to that enable allow_url_fopen() and using file_get_contents() with a fully qualified URL (http://...`) - as mentioned in a comment to the other answer - or did you have something else in mind?
    – Floris
    Apr 14, 2014 at 11:58
  • No, its just setting up PHP to read in and conform to the rules of .htaccess, of course this would have to be programmed into your PHP. In essence, what I am stating is that in theory it would work if one were to take the time to program it to work in that manner, yet, would you want to do it that way, would be a better question to be asking. Apr 14, 2014 at 16:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.