Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
499 views
in Technique[技术] by (71.8m points)

html - 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:

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

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...