Steeven
Steeven

Reputation: 4200

Sessions and php redirect doesn't work

I am making a PHP script check.php that checks if a user is logged in. There is only one user, so the password is written directly in the php code. The check.php is included at the top (line 1) of every relevant page with the line <? include "check.php"; ?>.

The code

I have removed the password and the domain name. Apart from that the following is my code. The point here is that you type in a password at a login page, and then send it by POST to this script.

If the password is correct xxx, the session login will store true.

If the password is not correct, but is set, meaning the user typed in something wrong, any existing session is ended with session_destroy(), meaning he is logged out.

If he reaches a page but is not logged in, the session login should be false or not set, meaning that the } elseif(!($_SESSION['login'])) { will be used.

Lastly, if he clicks a logout button he is send to this script with the url: check.php?logout=true. The logout=true should be caught in the $_GET in the final elseif statement, and the session should be ended in there.

<?
ob_start();
session_start();


if($_POST['password'] == 'xxx') {   // Correct password

    $_SESSION['login'] = true;
    header("Location: http://www.url.com/administration/index.php");

} elseif (isset($_POST['password'])) {  // Wrong password

    session_destroy();
    header("Location: http://www.url.com/administration/login.php?true");

} elseif(!($_SESSION['login'])) {   // Check at every page

    header("Location: http://www.url.com/administration/login.php");

} elseif($_GET['logout']) { // Log out

    session_destroy();
    header("Location: http://www.url.com/");

}
ob_flush();
?>

The problem

In every if statement I try to redirect. I use the header("Location:...), but it doesn't work in any of the cases. Because the header command must be the first request to be send to the browser according to the specs, I used the ob_start(); and ob_flush(); as described here. It doesn't work with or without these.

Also there is a problem with the session that will not store content. I can't store true in the session of some reason. Is there a problem with my code that makes it fail?

As a test I have tried to write an echo command in every if / ifelse statement. From that I found that the script always enters the third statement - the one with the !($_SESSION['login']).

The question

So far so good. This tells me that the script is able to detect that the session is not set.
The two problems that remain are:

Any advice will be appreciated.


Update 1

To make it clear what happens (and what doesn't happen) I have put in some echos at different spots. This snippet of the above code with some additional echos:

...
echo "Input: " . $_POST['password'];
echo "<br>Session before: " . $_SESSION['login'];

if($_POST['password'] == 'xxxx') {  // Correct password

    $_SESSION['login'] = true;
    header("Location: http://www.url.com/administration/index.php");
    echo "<br>Session after: " . $_SESSION['login'];
    echo "<br>The first if works";

} ...

returns the following output:

Input: xxxx
Session before:
Session after: 1
The first if works

(The xxxx is the password; and it is correct.)

This is a situation where you are loggin in. You have just written the password and has been sent to the check.php.

So, I can see here that it accesses the first if as it is supposed to. And the session is correctly set to true (or 1). When I refresh the page the session is not set anymore though. Shouldn't it be?

And the header redirect clearly doesn't do anything.


Update 2

So, thanks to the answer from @EmilF below, I found that my session id - which I could print to the screen with echo session_id(); - changes at every page shift or page refresh to some new random number it seems. I looks as if the data stored in the session is then forgotten, because the new session id points somewhere else.

By using:

<?
session_id('cutckilc16fm3h66k1amrrls96');
session_start();
...

where cutckilc16fm3h66k1amrrls96 is just a random number, the session id is fixed, and the stored data can now be retrieved again after page refresh. This works quite well; though still a bit odd it is necessary.

Now I only need the header redirect to work...

Well, this smells like something that has been shut off. The session and the header functionality are changed. Maybe this is some PHP setting from the host. Something that blocks the header request.

To be continued...

Update 3 - solved

See my answer below.

Some strange symbols are created in the beginning of the file when I change the file into another coding format, e.g. from ANSI to UTF-8. The symbols created are , and I cannot see them in my own editor. Because they are in front of the php script they prevent the header and session_start() to work proporly. Why they are created there is still a mystery to me.

Upvotes: 6

Views: 9059

Answers (4)

Dejan Marjanović
Dejan Marjanović

Reputation: 19380

Mystery solved here: Byte Order Mark

enter image description here

Best answer you will find:

https://stackoverflow.com/a/8028987/424004

Upvotes: 2

Steeven
Steeven

Reputation: 4200

After many long days and nights of testing, reading and asking and with a lot of help from the participants on this question - thanks a lot for your effort! - I slowly reached this rather mysterious solution to the problem.
A solution I found, but an explanation I still don't have...

So, as described in Update 2, I found from the answer from @EmilF that the session id changed constantly. A thought was then to suspect a server / host issue. I contacted the host - one.com - who at first like me didn't understand, why it didn't work.

But then he told me, there was some rather odd symbols in the beginning of the check.php file. I couldn't see them in my own editor. They weren't visible until I accessed the file via the FileManager software that one.com provides browser based.

The issue and solution

The top of the file looked like this:

<?
ob_start();
session_start();


if($_POST['password'] == 'xxx') {   // Correct password

    $_SESSION['login'] = true;
...

You can see the odd symbols  in the beginning. As I said, they were not visible in my own editor Notepad++, nor in regular Notepad. I sent the file to a friend to check, and he couldn't see them either in his editor, Coda.

These symbols would of course act as output to the browser. Therefor this is a request to the browser that occours before the session_start() and the header(Location:.... Because those two commands must be prior to any browser request, they don't work now in this case with the symbols present.

Sessions and header command work perfect now with the symbols removed.

Still no explanation...

I have no idea why they are there, but after more testing I found out how they got there:

In Notepad++ I can change the coding format in the menu. When I change from fx ANSI to UTF-8, the symbols have appeared. In normal Notepad I can save as UTF-8 as an option in the "Save as" window. And the symbols also appear in this case.

In any case I can only see the symbols , when I view the code through a browser based editor that takes the files directly from the server. And nomatter the editor it is always  that are created.

I don't have the explanation for this. This might be a good topic for another SO question.

Thanks to all who tried to help me. I am answering the question here, because this is the answer. But all help and debugging tricks have been much appreciated and very helpful.

Thanks a lot and have a good summer all of you.

Upvotes: 0

EmilF
EmilF

Reputation: 109

Try printing the PHPSESSID with session_id(). Do you get the same output if you keep refreshing?

If not try to set the id with: session_id('cutckilc16fm3h66k1amrrls96')

http://php.net/manual/en/function.session-id.php

It should work now, but with the same session for all users.

The problem could be something like this: PHP Session data not being saved

Upvotes: 1

aufziehvogel
aufziehvogel

Reputation: 7297

Okey, let’s list everything you can debug here, mentioning also stuff you already did (so other people can read it):

  • Do you have something like HTTP Header installed? Then you can see if the Location: header is sent to your browser or not.
  • I suppose you do not get any error messages, do you? Have you set error_reporting(E_ALL);?
  • Try doing var_dump() for the $_POST array.
  • Do you also have something to check cookies with in your browser? I usually use the Firefox web-developer toolbar plugin which has a menu Cookie -> show cookie information. There you should see a PHPSESSID cookie (after login). If not, your URL should include some information about the session id (looks like this: ?PHPSESSID=514515ca274866b9f0b5b2520b6fcbb4). Otherwise, PHP cannot find a session, because it does not know which session belongs to you.

If this does not help check if the cookie is set:

  • Again open your header plugin and then perform a login. Check if the server sends a cookie to you. This must be done in a Set-Cookie command. It might look like this: Set-Cookie: PHPSESSID=514515ca274866b9f0b5b2520b6fcbb4; path=/
  • If the server does not set a cookie, check for the settings in php.ini. There must be a setting session.use_cookies = 1 which must be set to 1 or On to allow PHP to use cookies.
  • If the server does set a cookie, but your browser does not allow it, check the options of your browser for cookies. Also check the php.ini setting for session.use_only_cookies = 0. If this is set to 1 you forbid PHP to use the URL if a cookie is not accepted by the browser. This is usually forbidden for security reasons, because people copy URLs to friends and then these friends will take over the logged in session ;) So just set it to 0 for debugging purposes.
  • var_dump() the return value of session_start(). It will return false if PHP was not able to start the session correctly.

Upvotes: 3

Related Questions