Question

I am wondering how to best deal with a return url in a login form. I think a good way is probably how it is done here. That is to urlencode the current url and send it as a get parameter to the login controller.

This can then be urldecoded in the login controller. But what then? I looked at the StackOverflow login page, and I couldn't find that url anywhere. Where is it stored? How does it know where to go when the login is done? Is it stored in a cookie? Session variable? Or something else?

I guess things can be done a bit differently than in PHP, but anyways. What is a good way to do this?

Was it helpful?

Solution

If it's a static URL, then you can include it on the form as a hidden field and then redirect to it in your code, i.e.

<input type='hidden' name='return' value='/thankyou.html' />

Then in your submit function ...

header("Location: $_POST['return']");

In production, you'll obviously want to encrypt the URL in the hidden field, and then decrypt it and validate it as a good URL before invoking the header() function, but that should give you the idea.

Some folks use cookies, others have a lookup table in the DB. Doesn't really matter where you store the URL, it's just important that you scrub it before you header() it.

EDIT: Scrubbing

function isValidURL($url) {
   return preg_match('|^http(s)?://[a-z0-9-]+(.[a-z0-9-]+)*(:[0-9]+)?(/.*)?$|i', $url);
}

if ( isValidURL($_POST['return']) )
    header("Location: {$_POST['return']}");

As I said earlier, if you want to be even more careful, you can encrypt/decrypt the actual URL prior to showing on the form and prior to validation. There's a ton of good encrypt/decrypt libraries out there.

The take home lesson is to never actually "do anything" (such as insert values in a database, run a shell command, redirect to a URL, etc) with data that comes in via form. Someone could manipulate that hidden field and inject code into your app or db by being tricky. There's thousands of posts an examples of things that people will do through form injection.

OTHER TIPS

If it were me, I would set the return URL in a session. This way you can calculate the appropriate URL and keep things separate from the presentation layer. Upon detecting a return URL is set, and a post object is present, you can set the location header and exit the script. Example...

// You have the URL to return to (could be a constantly updated session variable
// or simply set when a certain page is accessed via HTTP_REFERRER - it's open)
// in a MVC application (like stackoverflow) you could add this to the controller
// for any view with return functionality.
$_SESSION['RETURN_URL'] = $Url;

// Now you have validated and processed a form (from the model). If there is a 
// return url set, we redirect to it. Otherwise, we follow the default action of 
// the form
if ($FormValidatedAndSubmitted)
    returnToURL();

function returnToURL(){
    if (isset($_SESSION['RETURN_URL'])){
     header("Location: " . $_SESSION['RETURN_URL']);
     unset($_SESSION['RETURN_URL']);
     exit();
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top