0

I am trying to prevent direct access to a particular file within a sub-folder.

I realize that there are MANY topics depicting similar issues here on this forum. But, mine seems to be a bit awkward........due to my already existing HTACCESS file.

Here is the file-path to the file :

www.example.com/PRINCIPAL/PROJECTS/my_file.php

(my_file.php is the file I want to restrict from direct access)

What I mean is : my_file.php is current accessible only if the user navigates through a particulae sequence of events within my website (such as : select radio-button here........click another button there, etc, etc)

I want it to stay that way.

Unfortunately, if the user attempts to access the file directly, by typing in the URL in his browser, he can also access my_file.php

Which is what I do not want.

The reason I say my situation is rather awkward is because : normally, this is an easy thing to fix :

(a) include a rule in the HTACCESS file which would prevent direct access to the file itself (b) place the file in a separate folder, and then simply use DENY ALL in the htaccess file (c) place the file in a separate folder, and then create an EMPTY INDEX file, right next to it

And so on, and so forth

The reason why none of these would work for me is ---- as I mentioned above ---- due to my current HTACCESS file. It already contains two rules :

(a) a rule to remove all PHP file extensions (b) a rule to hide the sub-folder "PROJECTS" from view (in the browser bar)

Here is my current HTACCESS file :

 Options -Indexes
 Options -MultiViews
 Options +FollowSymlinks

 <IfModule mod_rewrite.c>

 RewriteEngine On

 RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/?([^/]+)/([^/]+)/([^.]+)\.php [NC]
 RewriteRule ^ /%1/%3 [R=301,L]

 RewriteCond %{REQUEST_FILENAME} !-d
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteRule ^([^/]+)/([^/]+)/?$ $1/PROJECTS/$2.php [NC,L]

 </IfModule>

So, as I mentioned earlier, this is the path to my_file.php :

www.example.com/PRINCIPAL/PROJECTS/my_file.php

With those two rules in my HTACCESS file, the actual file-path becomes :

www.example.com/PRINCIPAL/my_file

Because of this, those 3 solutions I listed above ---- A, B, and C --- would not work for me.

I cannot find anything online which addresses my particular problem. I am still new to this, but I am guessing that I would need to :

(a) somehow modify my current HTACCESS file (b) create a new and separate HTACCESS file, and place it in a separate folder, together with my_file.php

Any help here would be greatly appreciated

Thanks

UPDATE

I should have mentioned : "my_file.php" opens in a new window (child-window). I already to solve the issue by using $_SESSION variables to check whether or not the user made a particular necessary selection. Unfortunately, it did not work. When I checked the error-logs, I saw this message : UNDEFINED INDEX XXXXX.

Apparently, when the child-window is opened, the session variable is not carried forward (which is weird)

UPDATE

Here is the code from the parent-page :

  if(isset($_POST['submit'])  {

  $_SESSION['response'] = $_POST['selection'];

(The user must select a radio button, to proceed further).

Then, at the top of the child-window, I have this code :

if (!(isset($_SESSION['login']) && $_SESSION['login'] != '') ||    
   (isset($_SESSION['login']) && !(isset($_SESSION['response']))

{

header ("Location: /PROJECTS/access_denied");

The first part checks to make sure that the user is LOGGED IN.

The second checks to make sure that the radio-button was indeed selected on the previous page.

UPDATE

Once again, something I should have mentioned : (my head is just all over the place now). The child-window is a questionnaire program; it asks a series of questions, one at a time. Each time a new question is asked, the window refreshes. And it is the SAME php file (my_file.php). It refreshes each time, but displays a new question, depending on what the user selects on each preceeding page.

For this reason, the $_SESSION "check" needs to be valid, each time the child window refreshes.

If I UN-SET the session at the beginning of the first child-window, the next question will display the "Access_Denied" page !

And, you may ask : why bother to open this questionnaire program in a child window? Well, amongst other reasons, I disabled "Back button" and "Page Refresh" on this child-window, because it is important that the user not refresh this window once the questionnaire has begun.

EDIT

As a last resort, I suppose I could simply HIDE the file-name (my_file) from the URL address bar, so that the user does not know the name of the file, and therefore, will not know to actually look for it.

I tried changing the filename to "index.php", but this still shows in the address bar.

I have tried many ways to hide the file-name, but nothing seems to work

phpnewbie2015
  • 366
  • 2
  • 4
  • 17
  • Though there certainly is no example online which exactly matches your specific question I still don't see any point where this issue is somehow "awkward" or "special". You have to add a rule to your `.htaccess` style file, yes. Neither does this get complicated by the fact that there already is such a file (where to add otherwise?), nor is there any conflict with the contents of that file. – arkascha Jun 07 '15 at 12:54
  • Anyway, about your question: that specific need you post is questionable by itself: on the one hand you want to offer a file via some URL, on the other hand you want to block access. That does not make sense at all. The architecture is wrong. If that stuff really is meant as dynamic content, then don't put it into a file inside your document tree. Files are for static content to be delivered. The usual approach is to have some kind of controller, published via some URL. That controller can decide what content to deliver or not by whatever logic you want, don't push this onto the http level. – arkascha Jun 07 '15 at 12:56

1 Answers1

2

IMHO, allowing to access the PHP file only if the user goes a specific way to get there is not the right approach. A file on a web server should always be publicly accessible or not (and not sometimes yes, sometimes no).

My suggestion would be to collect information about the way the user took. You could, for example, store these data in the session and then analyze it, when your my_file.php is called. If you should observe, that the user has taken the "right" way up to now, you can execute your script as usual. If not, you should display an error message, or - if you want to - tell him, that he has no access.

Assuming you want to use a session for that purpose, you could place the following code on top of your my_file.php:

session_start();
if (!isset($_SESSION['login']) || ($_SESSION['login'] == '') || 
    !isset($_SESSION['response']))
{
    header ("Location: /PROJECTS/access_denied");
    exit;
}

//Process the request, as the user is now confirmed to be allowed to use this page

//In the end, possibly:
unset($_SESSION['response']);
//Now the user won't be able to use this page again until he "took the right way" again.

In your parent page, you would then use:

session_start();  
if(isset($_POST['submit'])  {
    $_SESSION['response'] = filter_input(INPUT_POST,'selection');
    //...
}

// I assume, that $_SESSION['login'] is set somewhere else.

This is just a very basic example. I think the key is gathering the information about how the user accessed your script.

When not using sessions, one might think about checking $_SERVER['HTTP_REFERER'] to check where the user came from, but then you should keep in mind, that many users don't send this information because of privacy considerations and even more, that the referer can be set to an arbitrary value by a client, so this is definitely not the right way.

Edit: Inserted code for using the session as in your example. Did you remember to call session_start() on both the pages? I think the if statement at the beginning was messed up a little, so I tried to make at more simple. :) Also, I used filter_input as a very basic security enhancement when reading the POST variable.

ahuemmer
  • 1,653
  • 9
  • 22
  • 29
  • Perhaps I should have added that "my_file.php" opens in a new window (child-window). I already tried your approach : using $_SESSION variables to check whether or not the user made a particular necessary selection. Unfortunately, it did not work. When I checked the error-logs, I saw this message : UNDEFINED SESSION VARIABLE XXXXX. – phpnewbie2015 Jun 07 '15 at 13:07
  • Hmmm, but this is the approach that you should go after further, I think. I the server of the parent and the child window is the same, they also share the same session. You can always use things like `print_f($_SESSION)`o check, which variables are set in the session and which values they have. If you show me the code that did not work, I might be able to help you further. – ahuemmer Jun 07 '15 at 13:37
  • Sure. I updated my original post to include the code from the parent-page, and the code from the beginning of the child-page – phpnewbie2015 Jun 07 '15 at 14:21
  • Thanks again, ahuemmer; your code helped. At least, now, the $_SESSION variable is being carried over into the child_window. But.........the "my_file" is still accessible directly. :( :( – phpnewbie2015 Jun 07 '15 at 17:28
  • Maybe, I should point out (although, I guess, you already know this) : the code works BEFORE the child_window is opened. Meaning : BEFORE the user arrives at that particular parent-page (where the radio-button is selected). But, AFTER the user has made the selection, and opens the child-window, the code no longer works. Obviously, once the radio-selection is made ($_SESSION variable is set), it stays there permanently. This is the problem I am trying to eradicate! – phpnewbie2015 Jun 07 '15 at 17:30
  • I always assumed that Sessions are automatically destroyed once a window is closed, but apparently this is not the case. Once the user has made a radio-button selection, he can access the "my_file" page directly (as long as he is logged in). I have been trying to find a way to prevent this (((((( – phpnewbie2015 Jun 07 '15 at 17:32
  • Uh, I see... Normally, the session is permanent until a user deletes his cookies or a specific timeout with a default of 24 minutes is reached (look [here](http://stackoverflow.com/questions/4146647/destroy-php-session-on-closing) for another solution). But couldn't you just do something like `unset $_SESSION['response']` during your `my_file`script execution? I updated my code suggestion accordingly. – ahuemmer Jun 07 '15 at 17:51
  • Can we head over to chat-room? Stackoverflow is complaining that our comments are getting too long (hahaha) – phpnewbie2015 Jun 07 '15 at 18:18
  • Anyway, I updated my original post again, to explain my situation further. Thanks – phpnewbie2015 Jun 07 '15 at 18:40
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/79908/discussion-between-ahuemmer-and-phpnewbie2015). – ahuemmer Jun 07 '15 at 20:02