PHP: Cookies aren't working.



  • I really hope that this isn't going to be a WTF, but I'm having a bit of a problem with the user system for a web-based application using PHP. Upon sucessful login, a pair of cookies is supposed to be set: one containing the username, and the other containing the md5(password). However, the cookies aren't being set. Plus, even with an incorrect login, the "you have been sucessfully logged in" screen is still registering, and it forwards appropriately. However, it displays the "you are not logged in" screen no matter what when trying to access members-only pages, even with valid login. :
    <font size="2"><font face="Courier New" size="1">
    </font><font face="Courier New" size="1"><...HTML SNIPPED...>

    $username=$_POST['username'];
    $password = md5($_POST['password']);
    $info = mysql_query("SELECT * FROM nem_users WHERE username='$username'") or die(mysql_error());
    $data = mysql_fetch_array($info);
    </font><font face="Courier New" size="1">if($data['password'] != $password)
    {
    echo("<center><font color=red><b>Login Failed. Incorrect username or password. Please try again.</b></font></center>");
    }
    else
    {
    echo("<center><b> You have been successfully logged in. You will be redirected in a moment. </b></center>");
    setcookie("pass", "$user[password]", time()+(360024), "/", "");
    setcookie("username", "$user[username]", time()+(3600
    24), "/", "");
    echo("<meta HTTP-EQUIV="REFRESH" content="4; url=logged.php">");
    }
    </font>
    </font>
    See any glaring problems?

    Regards,
    Bradley Williams
    Northeast Metrology / Vantek

    <font size="2">Edit: </font><font size="2">tested on Firefox 1.5, IE6, IE7 Beta3. So it isn't an issue with cookie-blocking security. </font>



  • As an experiment, try taking out that meta refresh at the end.  Let your browser load the page, then navigate to logged.php manually.  See if the cookie gets set, and let me know how it turns out.

    Also, I think you have a SQL injection vulnerability in your username.



  • Unfortunately, the page still displays the error that I am not logged in. In addition, trying to echo('$_COOKIE['username']'); doesn't do anything.

    As for the SQL injection: indeed, it was an oversight on my part. Thank you.




  • Glad I could help a little bit.  PHP isn't exactly my happy place, but I'll try to help you until a real PHP dude comes along.

    Have you tried setting a hard-coded cookie value, like:

    <FONT face="Courier New" size=1>setcookie("test1", "test2", time()+(3600*24), "/", "");</FONT>

    outside the if block to see if you can set cookies at all?  You should probably comment out the other cookie sets, too.

    If that doesn't work, double-check the clocks on your client and server to make sure they match.



  • Make sure you set the cookies before any HTML (or any text) is echoed. It should give you a warning, but the warnings depend on your configuration.



  • Yeah, I think the problem is with the "<...HTML SNIPPED...>"
    cookies are part of the header, which has to be sent before any other html.  Php will send all of its headers as soon as it encounters any output. There are a few way around this. 

    The one I personally prefer, is do all of your business logic at the begining of the php file (or better yet, a seperate, included, php). After all the business logic is finish, handle any headers you need to (including cookies). THEN render the html/xml/whateverml.

    The other way to fix this. There is a way to tell php to buffer its output until the end of the program.  That allows you to change headers anywhere along the way, until the buffer is flushed at least.

    Oh, as a side note, although I prefer the first solution, the second one allows you to grab the buffer and filter it through something (such as Tidy).  Why not have nice looking HTML every time, without having to worry to much about formatting in php?

    :-)
    Good luck.



  • RFlowers,
    even trying to set the cookies at the top of the code before any HTML ends up giving me "not logged in" at the first members-only page. And again, $_COOKIE['username'] is blank when I try to echo it. Would it be easier for me to catagorize this as a WTF and start from scratch, or is htere another solution that I'm overlooking.?



  • You either have a typo, or you're outputting text before sending the header. Even a space before the <?php tag will trigger the HTML body being sent.

    Use a network sniffer, or firefox extension, to look at the data that is being sent from the server to the browser. I'm pretty sure that there won't be a cookie sent in the headers :-)

    If there really is a cookie header, then check your browser configuration as to why it's denying the cookie. It may be rejecting it by default (recent IE like to do that.) Maybe the domain or cookie path is set wrong, causing the browser not to send the cookie back.

    I do think that the code is messy enough to make starting over from scratch a good idea though :)
    Maybe take a look at the PEAR project and see what they offer for authentication. You're not the first person to need user logins, you know, it's probably been done before. A million times.





  • @Nandurius said:

    You either have a typo, or you're outputting text before sending the header. Even a space before the <?php tag will trigger the HTML body being sent.

    Use a network sniffer, or firefox extension, to look at the data that is being sent from the server to the browser. I'm pretty sure that there won't be a cookie sent in the headers :-)

    If there really is a cookie header, then check your browser configuration as to why it's denying the cookie. It may be rejecting it by default (recent IE like to do that.) Maybe the domain or cookie path is set wrong, causing the browser not to send the cookie back.

    I do think that the code is messy enough to make starting over from scratch a good idea though :)
    Maybe take a look at the PEAR project and see what they offer for authentication. You're not the first person to need user logins, you know, it's _probably_ been done before. A million times.

    http://pear.php.net/packages.php?catpid=1&catname=Authentication


    I think you can also use either telnet or ftp, I forget which, if you want to see the cookie headers.  Of course, you have to speak http.



  • @Oscar L said:

    I think you can also use either telnet or ftp, I forget which, if you want to see the cookie headers.  Of course, you have to speak http.


    You can use telnet to do that (not ftp), but it's not very practical as submitting a form via telnet means you have to generate the POST data yourself (including calculating the length of the payload.) Very awkward.
    The script, in this case, wouldn't set a cookie unless a correct authorization token was supplied, but otherwise you could..

    $ <font face="Courier New">telnet thedailywtf.com 80</font>
    Trying 66.232.98.150...
    Connected to thedailywtf.com.
    Escape character is '^]'.
    <font face="Courier New">GET / HTTP/1.1
    Host: www.thedailywtf.com
    </font>

    HTTP/1.1 302 Found
    Date: Thu, 27 Jul 2006 17:10:28 GMT
    Server: Microsoft-IIS/6.0
    X-Powered-By: ASP.NET
    X-AspNet-Version: 1.1.4322
    Location: http://thedailywtf.com/default.aspx
    Cache-Control: private
    Content-Type: text/html; charset=utf-8
    Content-Length: 152




  • Ok, I think I may have it.

    The last parameter in the setcookie function is a boolean indicating if the cookie should only be set over a secure connection. It is optional. Passing "" is probably resolving to 'true.'

    So instead of
    <font face="Courier New">  setcookie("pass", "$user[password]", time()+(360024), "/","");</font>
    try
    <font face="Courier New">  setcookie("pass", "$user[password]", time()+(3600
    24), "/");

    </font>Also, is <font face="Courier New">"$user[password]"</font> OK?  I would have expected <font face="Courier New">$user['password']</font>, maybe?



  • @R.Flowers said:

    Also, is <font face="Courier New">"$user[password]"</font> OK?  I would have expected <font face="Courier New">$user['password']</font>, maybe?


    Actually, either one will work, although I believe the latter is slightly faster (Not that it REALLY matters in PHP)

    The first will return a string, who's content is the value of $user['password'], the second one will just return $user['password'] (obvoiusly)



  • the problem is that the cookie header can't be sent after actual content has been sent, this is a very common problem in php, simply move all the HTML to after the ?> tag, there should be nothing at all before the <?php tag, not even a space, as has already been said.



  • Excellent, thanks guys. Sure enough, I moved the setcookie() statements to the very top of the page, and it worked like a charm.

    This was a WTF on my part, I think, since I failed to read the setcookie() documentation fully. Thanks again, though.


Log in to reply