0

I'm attempting to implement basic session handling as follows:

PHP File 1 - login after various checks for the user and password etc in database I would like to give this user a session

<?php
...    
session_start(); 

PHP File 2 - before executing any logic in file 2 I would like to see if a valid session exists for the session that I believe would exist in the request PHPSESSID header?

<?php

$sessionID = session_id();    

if ($sessionID === '') {        
    echo 'no session found';
} else {
    echo 'session found.';
}    

I have attempted to start a new session in PHP file 2 which will return a value but the problem I have then is that if someone remotely attempts to execute a php file on my server, example https://example.com/folder1/php/loaddata.php they will simply be given a new session I and be allowed to execute the file.

BernardV
  • 640
  • 10
  • 28

4 Answers4

1

You need to add session_start() under the <?php tag on file 2 also otherwise it doesn't know about the session variables, etc.

It can be confusing though because you're not actually starting a new session, you're just continuing the existing one.

Let's clarify this more. Sessions themselves are not for authentication, they are more like a vehicle that makes it easier to track authentication across multiple web pages on the same site. Always check authentication against a user database. That being said, once a user is logged on successfully, you can do something like, $_SESSION['logged_in'] = true And that session variable is only going to apply to the user that is logged in. Then on the pages that required being logged in, you test to see if that session variable is set before loading the page, otherwise, redirect to a log in screen or whatever you wish. Does that clear things up?

Difster
  • 3,264
  • 2
  • 22
  • 32
  • If you simply start a session, then all users will by definition have a session, which means there's no effective login check. – deceze Aug 04 '17 at 08:21
  • If you check my last paragraph of my question, I do not wish to do this as then someone could still just execute the PHP file without having logged in. – BernardV Aug 04 '17 at 08:22
  • Yes, all users will have a session, that's why you have to authenticate against a user database. Sessions are not meant to track authentication as they are just as way to overcome the stateless nature of http and https. – Difster Aug 04 '17 at 08:22
  • @BernardV You have to write something to the session in file 1 that you can check agains in file 2. The session itself should always be started. – Björn Tantau Aug 04 '17 at 08:23
  • @BjörnTantau I always assumed you can check against the auto generated PHPSESSID that should be sent with every request to PHP? So if the ID does not exist on my server you can block access. – BernardV Aug 04 '17 at 08:25
  • The PHPSESSID is just used to identify the session storage. A simple `$_SESSION['logged_in'] = true;` in file 1 should suffice. If this is not set in file 2 you know that the user did not login. – Björn Tantau Aug 04 '17 at 08:27
  • File 2 still needs `session_start()` though which was part of my original point. Otherwise it won't know about the session data. – Difster Aug 04 '17 at 08:28
  • @Difster thank you for your effort in explaining this, I am testing and trying to figure this out on my side, I will mark the correct answer as soon as I can figure this out! – BernardV Aug 04 '17 at 08:49
  • Check back if you need more help. I've done a lot with forms. – Difster Aug 04 '17 at 10:25
1

The mere presence of a session doesn't mean much. You have to start a session before you can get the session id. PHP's default session handling doesn't really allow you fine grained control between starting a session and resuming an existing session; so any time you call session_start, which is necessary to get "the current" session id, a session will be started. This is no effective way to determine whether somebody is logged in.

But, in a login system you usually need to know who is logged in anyway, so you need to store a value in the session that indicates who the user is. Simply check for the existence/correctness of that value to determine logged-inness:

session_start();

if (empty($_SESSION['user'])) {
    header('HTTP/1.0 401 Unauthorized');
    exit;
}
deceze
  • 510,633
  • 85
  • 743
  • 889
  • I keep thinking that when a `session_start();` is triggered that browser / user would keep using the same PHPSESSID with each request to the PHP server (while the have a browser session open) and therefore I would be able to check against the PHP server's current session store for any active sessions with that PHPSESSID... – BernardV Aug 04 '17 at 08:31
  • `session_start` really means "initialise PHP's session handling sub system", which will *start* a new session if the browser didn't send a session cookie, or *resume* an existing session if the browser did send an existing session cookie. Therefore just checking whether there's a session id (after having initialised the session system) is rather pointless, because the answer is always *yes*. And before you call `start_session`, the answer is always *no*. – deceze Aug 04 '17 at 08:33
  • The built-in PHP session handling isn't that fine-grained. You could of course implement that yourself: check the cookies, if no session cookie exists, there's no session, if there's a session cookie, check whether it refers to a valid session, and only then read the session's data into memory. – deceze Aug 04 '17 at 08:37
1

This is a simplified explanation of the default php session mechanism:

When you start a session with session_start(); a unique session ID is generated and sent to the client via session cookie, so the next time that user comes to your website he can retrieve his session data (that is stored in a file on the server) with the session ID that was sent to him in a cookie.

That is done by comparing the session ID in the cookie and the name of the file that stores session data which has that ID in it's name.

To ensure that only a certain user can access some area of your website, you need to store a unique value in the $_SESSION global variable, for example:

<?php 
    session_start();

    if (!isset($_SESSION["user"]) || $_SESSION["user"] !== 'someValue'){
          echo 'not allowed';
    } else {
          echo 'allowed';   
    }

This is really a basic example, to make it more secure you need to do a lot more. You need to protect against CSRF, session hijacking/session fixation, you need to set_session_cookie_params() to allow only http cookies so that they cannot be altered with javascript. And in the end all this can be exploited if you are not using https, if you are be sure to set_session_cookie_params() to allow only secure connections (only over https).

deceze
  • 510,633
  • 85
  • 743
  • 889
Sasa Blagojevic
  • 2,110
  • 17
  • 22
  • After validating my user credentials against the DB, I attempt the following in my first php file: `session_start(); $_SESSION["logged_in"] = true; $_SESSION["user"] = $userName;` then on PHP file two I attempted the following simple test: `session_start(); $sessionUser = ($_SESSION["user"]); $sessionLoggedIn = $_SESSION["logged_in"]; echo $sessionUser; echo $sessionLoggedIn;` but no luck, I get `Undefined index` – BernardV Aug 04 '17 at 09:05
  • you need to put session_start(); in that new file too, session_start(); creates new sessions or continues old ones if the client has the session cookie – Sasa Blagojevic Aug 04 '17 at 09:07
  • thanks, but as you can see in my comment above it's the first thing I did in php file 2 :? – BernardV Aug 04 '17 at 09:08
  • call `session_commit();` before you redirect to the new file to ensure that the session is written in the file. – Sasa Blagojevic Aug 04 '17 at 09:12
  • Thanks @blackcat this was my mistake as I was calling the php file directly in browser and I should probably do an !isset as your example shown above, checking now! – BernardV Aug 04 '17 at 09:17
0

So based on responses from @deceze, @Difster and @blackcat I have implemented the following:

login.php

//start a session
session_start(); 
//add some session data
$_SESSION["logged_in"] = true;                                                       
$_SESSION["user"] = $userName;
session_commit();

stuff.php

session_start();

if ((isset($_SESSION["user"])) && (isset($_SESSION["logged_in"]))) {        
    echo ('You shall pass:'.$_SESSION["user"]);        
    //stuff.php logic can start
} else {        
    header('HTTP/1.0 401 Unauthorized');
    exit;        
} 
BernardV
  • 640
  • 10
  • 28