6

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:

  • WHY the redirect in a statement doesn't work, since no redirect happens, and
  • WHY the session can't be set in the first place.

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.

Steeven
  • 4,057
  • 8
  • 38
  • 68
  • 1
    Is your PHP code before the HTML in your .php file? – Frederick Marcoux Jul 14 '12 at 18:17
  • The code above is a file by itself `check.php`. But that file is then included in the very top of the php-pages, where it is supposed to check if the login is valid. – Steeven Jul 14 '12 at 18:20
  • 2
    Do you have something like [HTTPLiveHeader](https://addons.mozilla.org/en-US/firefox/addon/http-header/?src=search) 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);` ? – aufziehvogel Jul 14 '12 at 18:20
  • http://stackoverflow.com/faq#dontask - Read FAQ !!! – kravemir Jul 14 '12 at 18:20
  • @Miro: I cannot see why the question should be wrong. ““I would like others to explain ______ to me”, then you are probably OK.” And he wants somebody to explain the error to him. – aufziehvogel Jul 14 '12 at 18:23
  • 1
    @Aufziehvogel I've read it again and I've changed opinion. First time I skimmed it and I thought it is something formed more for forum than for SE. – kravemir Jul 14 '12 at 18:34
  • 2
    Try doing print_r for the $_POST['password'] array. If non of the redirects are working, obviously your first if has something wrong in the code. – DrinkJavaCodeJava Jul 14 '12 at 18:48
  • @redelman431. When I try that the `$_POST['password']` is correct. It seems its not the `if` statements that are wrong, its the `header` that doesn't do anything. – Steeven Jul 14 '12 at 19:32
  • So, I have made an update to the question to show what the output is, when the user is giving som input to log in. It seems that the if works, and that the session is set correctly. But when the page is refreshed the session is empty again. How come? – Steeven Jul 14 '12 at 19:50
  • @Aufziehvogel. Thanks for the tricks. I have tried the `error_reporting(E_ALL);` but there are no error messages it seems. – Steeven Jul 14 '12 at 19:53
  • 1
    @Steeven: Okay, so next debug step: 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. Otherwise it’s clear why the session cannot be found. – aufziehvogel Jul 14 '12 at 19:57
  • 1
    try adding exit; under the headers. Maybe the rest of the page execution interferes with this behavior – Federkun Jul 14 '12 at 20:05
  • @Aufziehvogel. I use Chrome with a browser toolbox for this info. I have no PHPSESSID cookie. I'm not sure what you mean with the url info, but there is none in the url to see. So far so good... – Steeven Jul 14 '12 at 20:07
  • @Laxus. The `exit;` quits the execution fine. But still no session is saved and still no redirect works. :( – Steeven Jul 14 '12 at 20:10
  • 1
    @Steeven, you can replace `session_start()` with `var_dump (session_start());`, and give us the value? – Federkun Jul 14 '12 at 20:25
  • @Laxus. That returns `bool(true)`. Does that tell anything? – Steeven Jul 14 '12 at 20:29
  • 1
    @Steeven, is very strange that you don't receive errors with E_ALL. Maybe display_error is set to off? Can you add `set_error_handler(function() {throw new Exception();});` and see if an exception is thrown? – Federkun Jul 14 '12 at 20:37
  • About the `Location:` header, is it in the headers (you checked with *HTTP headers plugin*)? – aufziehvogel Jul 14 '12 at 20:38
  • Did you sanitize the type input? – DrinkJavaCodeJava Jul 14 '12 at 20:39
  • @redelman431. I did nothing to the input while i'm testing. It's pure form input. – Steeven Jul 14 '12 at 21:07
  • So when you refresh the page you start the session again but this time without logging in. This is why there is nothing in the session variable upon refresh. – DrinkJavaCodeJava Jul 14 '12 at 21:35
  • @redelman431. What do you mean by `start the session again`? – Steeven Jul 14 '12 at 21:36
  • 1
    Assuming your executing the same php file on refresh, the code starts over from the first line. The beginning of your code says start session but this time you start a session again without the login information entered. – DrinkJavaCodeJava Jul 14 '12 at 21:38
  • Is it this one you mean? http://php.net/manual/en/function.session-start.php `session_start();`? As I understand it, this line must be set in order to work with sessions. I don't think it changes anything by itself. – Steeven Jul 14 '12 at 21:50
  • 1
    I don't think this will really make a difference but it's worth a try. I use single quotes in my header functions and they always work. Not saying thats the reason it does not work because really I have no idea. But I was just comparing a working one from your non-working one and my working one has single quotes. Just a shot in the dark. Im only saying this because the only difference I find is single quotes instead of double quotes. – DrinkJavaCodeJava Jul 14 '12 at 21:51
  • @redelman431. Worth a try, but made no difference unfortunately :) – Steeven Jul 14 '12 at 22:03
  • 1
    That is weird. Do you have any html on the same page before your php? I read on a site that having html before a header function makes it not work. – DrinkJavaCodeJava Jul 14 '12 at 22:12
  • Yes, the header must be the first request to the browser. http://php.net/manual/en/function.header.php. `"Remember that header() must be called before any actual output is sent, either by normal HTML tags, blank lines in a file, or from PHP"`. I have tried that. I have even tried putting the header on line 1 just after the `` start with all other content on the page commented out, but no luck either. It feels like something is turned off, blocking my header request. – Steeven Jul 14 '12 at 22:16
  • I have no clue then. Maybe you should start a bounty on this question. – DrinkJavaCodeJava Jul 14 '12 at 22:21
  • Question was updated. See update 2. Half of the problems are now solved somewhat. The header redirect issue remains. – Steeven Jul 14 '12 at 22:51
  • add this `register_shutdown_function(function() { var_dump(headers_list()); });` (or simply `var_dump(headers_list());` at the end of the page) and see what come out – Federkun Jul 15 '12 at 06:02
  • @Laxus. `var_dump(headers_list());` at the end of the page gives `array(2) { [0]=> string(24) "X-Powered-By: PHP/5.3.14" [1]=> string(23) "Content-type: text/html" }`. – Steeven Jul 15 '12 at 07:41

4 Answers4

3

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.
aufziehvogel
  • 7,167
  • 5
  • 34
  • 56
  • Why is this true: `"If non of the redirects are working, obviously your first if statement has something wrong in the code."`? – Steeven Jul 14 '12 at 20:34
  • Good question. Thought I understood it a few hours ago, but now I cannot get through. Just copied it from redelman431. I will remove it. – aufziehvogel Jul 14 '12 at 20:38
  • The php.ini seems to be deprecated or something. I used phpinfo(). As you say it should be, I found: `session.use_cookies` is on and `session.use_only_cookies` is off. – Steeven Jul 14 '12 at 21:09
  • Doesn't elseif statements go through each condition until one condition is true? – DrinkJavaCodeJava Jul 14 '12 at 21:13
  • @redelman431. if and elseif only tests their own conditions. If the `if` is true, then none of the following elseif's are executed. Its just a prioritized list of statements to test until one is true. – Steeven Jul 14 '12 at 21:23
  • Thats what I said, they go through each if and elseif and UNTIL one condition is true. So if the first condition is true, it goes no further. – DrinkJavaCodeJava Jul 14 '12 at 21:28
  • @redelman431. Okay, I misunderstood you. Yes thats what it does. But the if statements are not the problem here. See my update to the question above. – Steeven Jul 14 '12 at 21:30
  • I mean, if the if statements work or not has nothing to do with the header redirects working or not. And vice versa. Or am I misunderstanding this too? – Steeven Jul 14 '12 at 21:31
  • Yes you misunderstood. Im talking about a tottally different thing there. Im talking about when he refreshes and the session variable goes away. When I was talking about the if I was talking about when the redirects won't work. – DrinkJavaCodeJava Jul 14 '12 at 21:43
  • See my update 2 to the question. I've come down to just the header problem. I will try your header plugin idea soon to see what the header actually sends. – Steeven Jul 14 '12 at 22:50
2

Mystery solved here: Byte Order Mark

enter image description here

Best answer you will find:

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

Community
  • 1
  • 1
Dejan Marjanović
  • 19,244
  • 7
  • 52
  • 66
1

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

Community
  • 1
  • 1
EmilF
  • 109
  • 5
  • Well this did the trick :) At least for half of my problems. The session values are now stored even at page shift and refresh. It seems the session id was changed every time, which is prevented now. Thanks a lot! Now I only need the header to work... – Steeven Jul 14 '12 at 22:37
  • But won’t you run into trouble with your current dirty solution, if all people get the same session_id? I mean, it would mean if you have logged in and I visit your page, I get the same session_id and then I am logged in, too. – aufziehvogel Jul 15 '12 at 07:51
  • yeh, it is very dangerous .. Use `ini_set ('session.use_only_cookies', 1);` before `session_start ()` and try again .. @Steeven Be sure your browser has cookies enabled, eh – Federkun Jul 15 '12 at 08:06
0

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.

Steeven
  • 4,057
  • 8
  • 38
  • 68