Search code examples
phpauthenticationhttp-redirect

Redirecting to previous page after login?


After successful login, the user should be redirected to the page he came from, let's say he's been browsing a post and wants to log in so he can leave a comment, so he should be redirected to the post he was browsing. So here is what I have:

login.php shows the login form:

<form method="post" action="login-check.php">
... //input for username and password
</form>

The login-check.php checks if the username and pass are entered, does the user exist, or if he's already logged in, and a p parameter is sent to login.php:

<?php
session_start();
if((empty($username) OR empty($password) AND !isset($_SESSION['id_login']))) {
   header("Location:login.php?p=1");
   exit();
}
elseif (!user_exists($username,$password) AND !isset($_SESSION['id_login'])) {
   header("Location:login.php?p=2");
   exit();
}
elseif(isset($_SESSION['id_login'])) {
   header("Location:login.php?p=3");
   exit();
}
?>

then parameter p is sent back to login.php and displays the according message:

<?php
if(isset($_GET['p'])) {
  $p = $_GET["p"];

  if($p=="1")
    echo "<p class=\"red\">You didn't fill the form.</p><br></br>";
  if($p=="2")
    echo "<p class=\"red\">User exists.</p><br></br>";
  if($p=="3")
    header("Location: index.php");
}
?>

BUT, instead of going to index.php after successful login, it should go to the page the user has previously been. I've tried in different ways, but it either doesn't work at all or returns to login.php.


Solution

  • A common way to do this is to pass the user's current page to the Login form via a $_GET variable.

    For example: if you are reading an Article, and you want to leave a comment. The URL for comments is comment.php?articleid=17. While comment.php is loading, it notices that you are not logged in. It wants to send you to login.php, like you showed earlier. However, we're going to change your script so that is also tells the login page to remember where you are:

    header("Location:login.php?location=" . urlencode($_SERVER['REQUEST_URI']));
    // Note: $_SERVER['REQUEST_URI'] is your current page
    

    This should send the user to: login.php?location=comment.php%3Farticleid%3D17. login.php should now check to see if $_GET['location'] is populated. If it is populated, then send the user to this location (in this case, comment.php?articleid=17). For example:

    //  login.php
    echo '<input type="hidden" name="location" value="';
    if(isset($_GET['location'])) {
        echo htmlspecialchars($_GET['location']);
    }
    echo '" />';
    //  Will show something like this:
    //  <input type="hidden" name="location" value="comment.php?articleid=17" />
    

     

    //  login-check.php
    session_start();
    
    //  our url is now stored as $_POST['location'] (posted from login.php). If it's blank, let's ignore it. Otherwise, let's do something with it.
    $redirect = NULL;
    if($_POST['location'] != '') {
        $redirect = $_POST['location'];
    }
    
    if((empty($username) OR empty($password) AND !isset($_SESSION['id_login']))) {
        $url = 'login.php?p=1';
        // if we have a redirect URL, pass it back to login.php so we don't forget it
        if(isset($redirect)) {
            $url .= '&location=' . urlencode($redirect);
        }
       header("Location: " . $url);
       exit();
    }
    elseif (!user_exists($username,$password) AND !isset($_SESSION['id_login'])) {
        $url = 'login.php?p=2';
        if(isset($redirect)) {
            $url .= '&location=' . urlencode($redirect);
        }
       header("Location:" . $url);
       exit();
    }
    elseif(isset($_SESSION['id_login'])) {
        // if login is successful and there is a redirect address, send the user directly there
        if($redirect) {
            header("Location:". $redirect);
        } else {
            header("Location:login.php?p=3");
        }
        exit();
    }
    

    Gotchas

    You should run some validation against $_GET['location'] before sending the user there. For example, if I tell people who use your site to click on this link: login.php?location=http%3A%2F%2Fmalice.com%2Fevilpage.php... then they will be sent to a foreign URL that will try to do something bad.

    Always make sure to use urlencode when passing URLs as $_GET parameters. This encodes special URL characters (such as ?, &, and %) so that they don't break your url (e.g.: login.php?location=comment.php?id=17 <- this has two ?'s and will not work correctly)