I have some small applications that I want to secure.  I've been using the following setup that I think is fairly safe, but I've never been able to set my mind at ease that it really is. Could you give me some reviews on the security of this?  It doesn't need super-security like credit card data, but I suppose secure is secure.Cookie-based Sessions. User table is:  Username field (cleartext)  Random/unique salt field (created with mt_rand() at signup  Password field (SHA256 hash)(among other stuff)Login method takes username, looks for the DB row, gets the salt, adds it to the end of the posted password, calcs a SHA256 hash for that string, and compares that to the password field in the DB.auth.php include at beginning of app<?phpsession_start();if(!isset($_GET['logout']) && isset($_SESSION['user']) && $_SESSION['ipadd'] == $_SERVER['REMOTE_ADDR']) {    // currently logged in        // setup data     require_once('lib/functions.php');    $db = new ezSQL_sqlite('./','main.db');    $user = new user($db,$_SESSION['user']);    return;}// build login form$head = '<html><head><title>Please login</title><style type=text/css>h2 { margin-top: 75px; margin-left: 100px; }</style></head><body>';$form = '<form method=post action='.$_SERVER['PHP_SELF'].' id=userLogin>    <table><tr>    <td>UserName:</td><td><input type=text name=username value='.$_POST['username'].'></td>    </tr><tr>    <td>Password:</td><td><input type=password name=pass /></td>    </tr><tr>    <td>Remember me on this computer</td>    <td><input type=checkbox name=remember value=1 /></td>    </tr><tr>    <td>&nbsp;</td>    <td><input type=hidden name=loggingin value=true />    <input type=submit value=login />    </td></tr></table>    </form></body></html>';$msg[1] = '<h2>You\'ve logged out.</h2>';$msg[3] = '<h2>That username and password didn\'t match anything on record.</h2>';$msg[4] = '<h2>You must login to use this application</h2>';// used logout buttonif($_GET['logout'] == 'true') {    setcookie('SaveMe','',time()-3600);    session_unset();    die($head.$msg[1].$form);// trying to login from form or returning with 'save me' cookie} elseif ($_POST['loggingin'] == 'true' || isset($_COOKIE['SaveMe'])) {    require_once('lib/functions.php');    $db = new ezSQL_sqlite('./','main.db');$loginName = (isset($_POST['username'])) ? $_POST['username'] : $_COOKIE['worshipSaveMe'];    // ADDED: escaping of posted/cookie data;$loginName = mysql_real_escape_string($loginName);        // try to create new user object, error on fail    try {        $user = new user($db,$_POST['username']);    } catch (Exception $e) {        die($head.'<h2>'.$e->getMessage().'</h2>'.$form);    }        // try to login with user object, die on fail    if( ! $user->login($_POST['pass']))         die($head.$msg[3].$form);    else {                // if remember me box was checked        if($_POST['remember'] == 1)            setcookie('worshipSaveMe',$_POST['username'],time()+60*60*24*365);         return;    }// no post data, no save me cookie, just got here} else {     die($head.$msg[4].$form);}And the relevant part of the user class:class user{    private $username;    protected $ID;    private $created;    private $salt;    private $password;    private $db;    function __construct ( ezSQL_sqlite $db, $postedUsername ) {        if( !$user = $db->get_row(SELECT * FROM users WHERE uname = '$postedUsername';))            throw new Exception ('That username didn\'t match anything on record.');        else {            $this->db = $db;            $this->username = $postedUsername;            $this->ID = $user->user_id;            $this->created = date('Y-m-d',$user->createdDate);            $this->salt = $user->salt;            $this->password = $user->pword;        }    }    /** check password for match     * @param user input from a posted form     * @return boolean      */    private function verifyPassword($postedPass) {        $pHash = hash('sha256',$postedPass . $this->salt);        if($this->password != $pHash)            return FALSE;        else            return TRUE;    }    /** This relies on cookie based sessions, and so      * must be called before any output to browser.     * @return bool     */    public function login($postedPassword) {        if( ! $this->verifyPassword($postedPassword) ) {            return FALSE;        } else {            if( isset( $_COOKIE[PHPSESSID] )) { //be sure session was initialized                $_SESSION['user'] = $this->username;                $_SESSION['ipadd'] = $_SERVER['REMOTE_ADDR'];                return TRUE;            } else {                die('Session must be initialized before calling login method.');            }        }    }
Securely handling a password protected application
php;mysql;security;authentication;session
I see you check for sql injection of the loginname: $loginName = mysql_real_escape_string($loginName);Do you filter bad content for the submitted password?  Now that I look at it, you are sending the POSTed login name straight to the SQL, aren't you? This:new user($db,$_POST['username']);Should be this:new user($db,$loginName); If I'm reading this correctly - you need to sanitize the password also!This is generally very important. You are also using MySQL functions to sanitize SQLite data.  That's probably okay, but I wouldn't bet the farm on it!