2

My first post here guys. Thanks in advance for any answers :)

Anyway, I have a login script (login.php) that has the following code upon submission of the credentials:

if(isset($_POST['submit'])) {

$password=$_POST['password'];
$email = (string)$_POST['email'];

try {
$db = new PDO('mysql:dbname=dbname;host=localhost', 'username', 'password'); // MY REAL DETAILS ARE USED HERE, JUST DON'T NEED THEM ON THE INTERNET
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}
$sth = $db->prepare('SELECT * FROM members WHERE email = :email LIMIT 1');
$sth->bindParam(':email', $email);
$sth->execute();
$user = $sth->fetch(PDO::FETCH_OBJ);

// Hashing the password with its hash as the salt returns the same hash
if (crypt($password, $user->password) == $user->password) {
    if($user->id > 0) {
        if($user->status == 'Y' && date('Ymd', time($_SESSION['expiration'])) == date('Ymd')) {
            $data = array('status' => 'D');
            $update = mysql_update('members', $data, '`id`='.$_SESSION['memberID']);
        } 

        $status = mysql_select('SELECT status FROM members WHERE id='.$user->id);
        $_SESSION['memberID'] = $user->id;
        $_SESSION['expiration'] = $user->expiration_date;
        $_SESSION['timeout'] = time();

        if(isset($_REQUEST['url'])) header('Location: '.$_REQUEST['url']);
        else header('Location: account.php');
    } else {
        $error = "Whoops! That wasn't supposed to happen, please contact the webmaster.";
    }
} else {
    $error = "Sorry, something didn't quite match up. Please try again.";
    // print $user->password;
    // print "<br />";
    // print crypt($password, $user->password);
}
}

The problem is that when $_REQUEST['url'] is set, the redirect occurs BUT is sent right back to my login script.

Example: my url is mysite.com/login.php?url=account.php and I click submit on login. It runs through the above code, and sends me straight back to login.php as if the session wasn't set. The code that tells account.php to go back to login is this:

if(!isset($_SESSION['memberID'])) header('Location: login.php?url=account.php');

I don't understand why, but when I do a hard refresh CTRL + F5 the session IS set and it takes me back to index.php because login.php says

if(isset($_SESSION['memberID'])) header('Location: index.php');

I'm pulling my hair out because this bothers me so much. Any help is appreciated.

I'm Using PHP version 5.3.26 just if you guys are curious. I know when my session is set because i have a page (php.php) that prints out my session with var_dump($_SESSION);

Thanks!

Edit: My Problem is not the redirect. Logically this is what should happen, in order:

  1. User enters login data and clicks submit
  2. The login page then checks their data
  3. Set Session Vars
  4. Go to account.php

Account.php should see if my session is set if(!isset($_SESSION['memberID'])) header('Location: login.php?url=account.php'); so this line is the part that is not reading my session.

Back at login.php the session is set with:

$_SESSION['memberID'] = $user->id;
$_SESSION['expiration'] = $user->expiration_date;
$_SESSION['timeout'] = time();

if(isset($_REQUEST['url'])) header('Location: '.$_REQUEST['url']);
else header('Location: account.php');

This part HAS to be working because the session IS being set AND going to account.php, but account.php is not reading the session when it is set. WHY?

This is NOT a cache problem either because I've cleared my caches and tried to limit caching of my page as well.

Ryan Ginnow
  • 83
  • 10
  • 1
    Do you call session_start() before everything in the script? – Roberto Sep 04 '13 at 23:08
  • I must be missing something, because how do you get $_REQUEST['url'] when you only check for it if $_POST has occurred? Are you setting it somewhere in code you haven't provided? – timgavin Sep 04 '13 at 23:24
  • @Roberto - Yes session_start() is on EVERY page. – Ryan Ginnow Sep 06 '13 at 16:11
  • @Tim - mysite.com/login.php?url=account.php <- $_REQUEST['url'] is set in the actual page url – Ryan Ginnow Sep 06 '13 at 16:11
  • Yes, but you're looking for it INSIDE of your $_POST. See my answer for clarification. – timgavin Sep 06 '13 at 16:36
  • What is the point of capturing the url? You may be making this more complicated than it needs to be... – timgavin Sep 06 '13 at 17:28
  • @Tim - I need to know if the user has come from a page that requires them to be logged in. Again, the redirect is not my problem. The session is. – Ryan Ginnow Sep 06 '13 at 17:31
  • You check if they need to be logged in by putting if(!isset($_SESSION['memberID'])) {} at the top of every page. You shouldn't need to check the url. – timgavin Sep 06 '13 at 17:35
  • That is what I'm trying to say. That code isn't working for some reason. I HAVE that code in my question. – Ryan Ginnow Sep 06 '13 at 17:59

2 Answers2

0

First of all make sure, you have this on the entry point of your app:

if (!session_id()) session_start();

Also, in the place when you do a redirect, do something like this (also always root URLs are good):

header('Location: account.php');
die();
Kleskowy
  • 2,648
  • 1
  • 16
  • 19
  • Could you elaborate on why this is needed? session_start() would need to be called regardless of anything else wouldn't it? Otherwise you can't access anything session wise, so the if() wouldn't be really be needed in my opinion. Also, why die after a header if "logically" the header would already be sending the user to the redirect. Seems to me the code would "die" anyway upon redirect... – Ryan Ginnow Sep 06 '13 at 16:16
  • You always have to call session start or have a config file which contains the function as it's first function call. – Jonast92 Sep 06 '13 at 16:38
  • @Jonast92 - That's what I thought. Session_start() is the first thing on EVERY page of mine, so this isn't a problem. – Ryan Ginnow Sep 06 '13 at 17:08
  • @Minnow990 Yes, I was basically backing up the point. I didn't realize that you were OP. What matters is that we're on the same page. – Jonast92 Sep 06 '13 at 17:54
0

Your sequence of events is a little off...

<?php
// you need session_start() at the top of each script in which you want to use sessions
session_start();

// check if the url parameter is passed *outside* of the isset($_POST['submit']) block
if(isset($_GET['url'])) {
    $url = strip_tags($_GET['url']);
    header('Location: '.$url);
} else {
    header('Location: account.php');
}

if(isset($_POST['submit'])) {
    // the rest of your stuff here...

This should give you an overview of the chain of events...

login_form.php

if($_SERVER['REQUEST_TYPE'] == 'POST') {

    $password = strip_tags(trim($_POST['password']));
    $email = (string) strip_tags(trim($_POST['email']));

    // perform database validation here...

    // check if validation successful
    if($validated == true) {

        // set your sessions and other stuff here...

        // redirect to the account page
        header('location: account.php');
    } else {
        $error = 'Your email and password do not match';
        // page will display the form again and echo the error message
    }
}
?>

<?php
    if(isset($error)) {
        echo $error;
    }
?>
<form action="login_form.php" method="post">
    <input type="text" name="email">
    <input type="password" name="password">
    <input type="submit" name="submit">
</form>

account.php

<?php
session_start();

// put this at the top of EVERY page in which a user needs to be logged in

// see if user is logged in, if not, redirect to login form
if(!isset($_SESSION['memberID'])) {
    header('location: login_form.php');
}

Edit: added new blocks of code under hr

timgavin
  • 4,972
  • 4
  • 36
  • 48
  • So how come I cannot get it inside the block? I don't understand why. I will try it though... – Ryan Ginnow Sep 06 '13 at 16:39
  • Because $_GET and $_POST behave differently. If you NEED to have that in your $_POST block you'll need to $_GET the url parameter and put it into your form (perhaps in a hidden field?), then read it during $_POST. I suggest you read up on using $_GET and $_POST: http://www.php.net/manual/en/reserved.variables.get.php – timgavin Sep 06 '13 at 16:58
  • OK, but $_REQUEST is a global $_GET, $_POST, $_COOKIE variable is it not? Besides, changing to $_GET or not wouldn't solve my session problem. The REDIRECT is not the problem, the SESSION not being read is my problem. – Ryan Ginnow Sep 06 '13 at 17:09
  • Yes, but in a previous comment you mentioned login.php?url=account.php is how you're passing the url parameter - well, that's not going to be read during a $_POST (usually). When you submit the form, look at the URL in the address bar. Does it contain?url=account.php? Probably not. So how are you going to get that value? Have you put session_start() at the VERY top of each script? – timgavin Sep 06 '13 at 17:17
  • Yes it is because I am not setting my form action to a different page. If you create a form without an action it does not change the url formatting. session_start() IS on every page because my session IS working, but account.php is NOT reading it for some reason... – Ryan Ginnow Sep 06 '13 at 17:20
  • Thanks tim, but this is EXACTLY what I already have. My problem is the !isset($_SESSION['memberID']) doesn't read correctly. – Ryan Ginnow Sep 06 '13 at 18:06
  • what happens when you var_dump($_SESSION['memberID']); ? – timgavin Sep 06 '13 at 18:10
  • It shows the member id... the whole session IS set BUT account.php won't read it right after the redirect... – Ryan Ginnow Sep 06 '13 at 23:35
  • Accepted this as answer because it is what I had, but after changing some other things throughout the site it seems to be working fine now. I'm not sure what was really happening, but this is no longer a problem. Thanks. – Ryan Ginnow Sep 11 '13 at 19:52