私はかなり標準的な Cookie ログイン方法を使用しています。ユーザーに 2 つの Cookie を与えます。1 つはユーザー名で、もう 1 つはランダムに生成された文字列とユーザー固有のソルトです。
これは、ログイン時に何が起こるかです:
$_SESSION['username']=$row[username];
$_SESSION['user_id']=$row['id'];
$loginhash=generateRandomBase64String()."_".$row['salt'];
$number_of_days = 14;
$date_of_expiry = time() + 60 * 60 * 24 * $number_of_days ;
setcookie( "userlogin", $row['username'], $date_of_expiry, "/" ) ;
setcookie( "loginhash", $loginhash, $date_of_expiry, "/" ) ;
$cryptedhash=crypt($loginhash);
$today=date("Y-m-d");
mysql_query("update members set last_login='$today',loginhash='$cryptedhash' where id='$row[id]' ") or die(mysql_error());
したがって、$loginhash
値は次のようなものPe0vFou8qe++CqhcJgFtRmoAldpuIs+d_g5oijF76
で、その暗号化されたバージョンがデータベースに保存されます。ソルトは、サインアップ時に各ユーザーに対して生成されるため、データベースに既に存在します。
セッション変数 ( $_SESSION[username]
) を使用して、ユーザーのログイン状態を維持します。次に、ユーザーがサイトにアクセスしたときに、次の 2 つのことを確認します。$_SESSION[username]
が設定されていない場合は$_COOKIE[userlogin]
、ユーザーがログインできるようにハッシュが正しいかどうかを確認します。問題は、ハッシュが決して正しくないことです。
if($_COOKIE['userlogin'] && !isset($_SESSION[user_id])){
$username=mysql_real_escape_string($_COOKIE['userlogin']);
$loginhash=mysql_real_escape_string($_COOKIE['loginhash']);
$salt=substr($loginhash,-8);
$result=mysql_query("select * from members where (username='$username' || email='$username') && salt='$salt' limit 1 ") or die (mysql_error());
$row=mysql_fetch_assoc($result);
$cryptedhash=$row['loginhash'];
if (crypt($loginhash, $cryptedhash) == $cryptedhash){
$_SESSION['username']=$row[username];
$_SESSION['user_id']=$row['id'];
}
}
$_COOKIE[userlogin]
が正しい値です。データベースでユーザー名とソルトの組み合わせを確認すると、正しい結果が見つかりました(echo $row[username]
正しい値が得られます)。ただし、それif
以下の条件は決して満たされません。PHP の構成に何か奇妙な点があると思いますが、同じ暗号化メカニズムを使用してパスワードを保存すると、正常に動作します。
では、ここで何が問題なのか誰にもわかりますか?
PS ここで、Cookie の安全性や利用可能なさまざまなハッシュ関数についての議論を始めるつもりはありません。