Trying to understand the Post/Redirect/Get design pattern (implemented with PHP)
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:
开发者_如何学JAVAheader('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
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);
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.
精彩评论