views:

70

answers:

2

All,

Sorry in advance - I'm not a PHP expert or knowledgeable in design patterns, so this question might be a little basic...

Anyway, I'm working on a web app that will require a login.

My plan is to have something like this:

index.php: this page will contain a simple form that allows users to enter a username and password. The form will POST the inputs to...

login.php: this page will receive the inputs from index.php, and check those credentials against a database. If any of the inputs are missing, or the credentials check fails, the php script will REDIRECT the user back to index.php using:

header('Location: http://www.mydomain.com/index.php');

If the credentials are valid, then login.php creates a session to establish the user's authenticated status:

session_start();
$_SESSION['authenticated'] = true;

Then, it determines what access type the user has. If he has "level 1" access, the script will redirect the user to level1.php using:

header('Location: http://www.mydomain.com/level1.php');

If the user has "level 2" access, the script will redirect the user to level2.php using:

header('Location: http://www.mydomain.com/level2.php');

Finally, when level1.php or level2.php is reached, the first thing they do is check the session. If the user is not authenticated, redirect him back to index.php:

session_start();
if (!isset($_SESSION['authenticated']) {
    header('Location: http://www.mydomain.com/index.php');
} else {
    // proceed to display the page
}

Having this check in level1.php and level2.php will prevent users from accessing that page directly, without logging in.

My first issue is this: this simple logic FAILS the first time through - when level1.php is reached, "isset($_SESSION['authenticated']" ALWAYS returns false, so the user is always redirected back to index.php. If he enters the exact same credentials a second time, the process works as it should.

In short, for reasons I don't understand, it seems the session that's set by login.php is not found by level1.php - I assume because of the redirect. In other words, the check on level1.php seems to fail until/unless a round trip is made to the client's browser.

Since every site that requires login has already solved this problem, this shouldn't be a novel challenge, and their should be a very established pattern for it. How should I handle it?

A related question... I've seen similar questions asked here before, and most answers usually involve a solution in which pages are POSTing back to themselves. This seems a little wierd - ideally, I'd like to have each PHP page perform a specific job:

  • index.php - display a form to capture credentials, then post them to login.php
  • login.php - evaluate the user's credentials, then direct them to the appropriate page
  • level1.php & level2.php - display the appropriate content

Is this a flawed setup? If so, what's the better setup?

And generally - if one page establishes a session, then redirects the user to another page - is there any way that second page can read the session?

There's a great page on Wikipedia about Post/Redirect/Get:

http://en.wikipedia.org/wiki/Post/Redirect/Get

But it's a little conceptual for me - I'd like to see it explained with references to specific pages:

E.g. a form on "page A" POSTs data to "page B", "page B" redirects the user to "page C", etc...

And, I don't understand how it's implemented with sessions, if sessions aren't recognized when using redirects.

Many thanks in advance for any advice and insights.


[UPDATE]

Thanks to Matt Ball's comment, I've refined the issue:

login.php was setting the session and redirecting the user to the next screen:

session_start();
$_SESSION['authenticated'] = true;
header('Location: http://www.mydomain.com/level1.php');

However, when level1.php checked that session, "authenticated" was NOT SET:

session_start();
echo (isset($_SESSION['authenticated']); // returns false

However, if I changed login.php so that the header redirected to a RELATIVE url instead of an absolute one:

session_start();
$_SESSION['authenticated'] = true;
header('Location: level1.php');

Then, level1.php works like I expect:

session_start();
echo (isset($_SESSION['authenticated']); // now returns true

I don't understand why the relative URL makes a difference, but it does. So, at least my immediate issue is resolved.

Many thanks to everyone who commented!


Cheers, Matt Stuehler

A: 

If the credentials are valid, then login.php creates a session to establish the user's authenticated status:

I'm shooting in the dark as well but I have the impression that you may output something before the setting the session in login.php. Place session_start as first instruction in every file.

mhitza
+1  A: 

Post Redirect Get comes in to play to stop a user resending their POST data if they refresh the page they've been redirected to after submitting a form. When you want to implement a PRG, you should set the HTTP header code to 303 like this:

header('Location: level1.php', 303);
Nev Stokes