已经发送了标头,这就是为什么不能设置cookie,而不是使用ob_start()在IE和Safari中专门工作的原因

已经发送了标头,这就是为什么不能设置cookie,而不是使用ob_start()在IE和Safari中专门工作的原因

问题描述:

I have login page in which I have a login form with action='checklogin.php'. It looks for username & password and if everything is alright, it sets email cookie & redirected to home page. I'm using ob_flush() at the start of checklogin.php because otherwise it gives you an error 'Headers already sent'. Now the problem is it works fine with Chrome, Firefox, Opera but not working in IE & Safari. Have a look at my code.

<?php
ob_start();
session_start();
include 'dbconnect.php';
$email = $_POST['email'];
$password = $_POST['password'];
$epassword = md5($password);
$q = "select * from users where email='$email' and password='$epassword'";
$r = mysql_query($q);
if ($obj = mysql_fetch_object($r)) {
    $time = time();
    if (isset($_POST['rememberme'])) {
        /* Set cookie to last 30 days */
        setcookie('email', $_POST['email'], time() + 3600 * 24 * 30, 'www.example.com');
    } else {
        setcookie('email', $_POST['email'], false, 'www.example.com');
    }
    echo "<script type='text/javascript'>";
    echo "window.location='index.php'";
    echo "</script>";
} else {
    echo "<script type='text/javascript'>";
    echo "window.location='login.php?message=Oops! Wrong Combination'";
    echo "</script>";
}
?>

Any idea what other things I should include or I should change to have it worked in IE? Excuse my formatting, it never displays correctly with Ctrl+K.

Your setcookie parameters are wrong. The fourth parameter should be the path, not the domain. I suspect the other browsers might be ignoring it because it doesn't begin or end with a /, which is why they cope with it, but it's still wrong.

For the fourth parameter, use '/' instead of 'www.example.com'.

P.S. Although it works, using ob_start() to fix headers already sent issues is really just a hack. The proper fix is to find and remove whatever is sending the early output. The error message will tell you where it is.

P.P.S. Your code is vulnerable to SQL injection because it doesn't escape the inputs. Without knowing the password, it's possible to log in as anyone by appending something like ' OR ''=' to the email address.

P.P.P.S. Your code seems to be based on old tutorials that are years out of date. The mysql_ functions are deprecated in favor of PDO and mysqli_. MD5 is totally unsafe for modern password hashing.

P.P.P.P.S. Storing only the email in a cookie is not a proper login cookie. Cookies can be easily edited by the user, making it possible to pretend to be anyone. Read about sessions, store the login info in the session object, and only store the session id in the cookie.

Find where in your code some output is being sent to the browser, and fix it. You may have the BOM error (byte order mark), or just a blank space or something in one of your includes.

Also - your code is wide open to SQL injection, you should switch to using mysqli/pdo or at least escape your user input. While you're doing that, learn about password security because a simple md5 is not good.