ユーザーをログインさせ、ページでのログインを検証するシステムのアイデアがあります。
そこにはたくさんのシステムがあることを認識していますが、主に自分のアイデアが何か良いものであるかどうかに興味がありました. 私はいくつかの調査を行いましたが、ほとんどの結果は、私が常に重要なプラクティスであると考えていたもの (パスワードの暗号化など) を除外しているようです。おそらくより安全な既製のソリューションを探すのは難しいでしょうが、アプリケーションのセキュリティを実際に扱ったことがなく、フィードバックを得たいと思っていました.
ユーザーがログインすると、名前とパスワードがデータベースに対して検証され、パスワードは SHA256 とランダムに生成されたソルトを使用して暗号化され、全体の文字列 (ソルトと暗号化されたパスワードの両方が 128 文字の長さ) になります。パスワード検証コードは次のとおりです。
function ValidatePassword($password, $correctHash)
{
$salt = substr($correctHash, 0, 64); //get the salt from the front of the hash
$validHash = substr($correctHash, 64, 64); //the SHA256
$testHash = hash("sha256", $salt . $password); //hash the password being tested
//if the hashes are exactly the same, the password is valid
return $testHash === $validHash;
}
ログインが有効な場合、トークンが割り当てられます。このトークンはパスワード暗号化に似ていますが、暗号化されたエポックと別のランダム ソルトを格納します。トークン、ログイン時刻、有効期限、ユーザー名をDBに格納し、ユーザー名とトークンをセッション情報として送信する。
トークンを作成するコードは次のとおりです。
function loginUser($email)
{
$thetime = time();
$ip = $_SERVER['REMOTE_ADDR'];
$dbuser="///";
$dbpass="///";
$dbtable="tokens";
mysql_connect(localhost,$dbuser,$dbpass);
mysql_select_db("///") or die( "Unable to select database");
//Generate a salt
$salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM));
//Hash the salt and the current time to get a random token
$hash = hash("sha256", $salt . $password);
//Prepend the salt to the hash
$final = $salt . $hash;
$exptime = $thetime + 3600;
//Store this value into the db
$query = "INSERT INTO `spanel`.`tokens` VALUES ('$final', $thetime, $exptime, $thetime, '$ip', MD5('$email') )";
mysql_query($query) or die ("Could not create token.");
//Store the data into session vars
$_SESSION['spanel_email'] = $email;
$_SESSION['spanel_token'] = $final;
return true;
}
ページに到達すると、持っているトークンとユーザー名が DB に対してチェックされます。チェックに問題がなければ、有効期限が更新され、ページが読み込まれます。そのコードは次のとおりです。
function validateUser($page)
{
//Grab some vars
$thetime = time();
$ip = $_SERVER['REMOTE_ADDR'];
$token = $_SESSION['spanel_token'];
$email = $_SESSION['spanel_email'];
$dbuser="///";
$dbpass="///";
$dbtable="tokens";
mysql_connect(localhost,$dbuser,$dbpass);
mysql_select_db("///") or die( "Unable to select database");
//Global var
//Get the var for token expire
$token_expire = 3600;
//Validate the token
$query = "SELECT * FROM `tokens` WHERE `token` LIKE '$token' AND `user_id` LIKE MD5('$email') AND `exp` > $thetime";
$result = mysql_query($query) or die(mysql_error());
//Check if we have a valid result
if ( mysql_num_rows($result) != 1 ) {
//Logout the user
//Destroy the session
session_destroy();
//Redirect
header("location: /spanel/login.php?denied=1");
exit();
//(Since the token is already invalid, there's no reason to reset it as invalid)
}
$row = mysql_fetch_assoc($result);
//Update the token with our lastseen
$newexp = $thetime + $token_expire;
$query = "UPDATE `spanel`.`tokens` SET `exp` = $newexp, `lastseen_ip` = $thetime, `lastseen_ip` = '$ip' WHERE `token` LIKE '$token'";
mysql_query($query);
}
フィードバック (良くも悪くも) は大歓迎です。私が言ったように、私はあまりセキュリティを行っていないので、ポインタを取得したいと思っていました.
編集:ログインシステムを効果的に作成する能力を過大評価しているのではないかと心配しています. そうは言っても、このおそらく欠陥のあるアイデアであるごちゃごちゃした混乱を理解しようとするのをやめようと決心したかどうかは理解できます。
それでも、ログインページのphpコードは次のとおりです。(ここで言われたことの後、パスワードを POST するだけでは大したことではないことがわかりました)。
$email = $_POST['email'];
$password = $_POST['password'];
$dbuser="///";
$dbpass="///";
$dbtable="///";
mysql_connect(localhost,$dbuser,$dbpass);
mysql_select_db("spanel") or die( "Unable to select database");
$query = "SELECT * FROM users WHERE `email` LIKE '$email'";
$result=mysql_query($query) or die(mysql_error());
$num=mysql_num_rows($result);
$row = mysql_fetch_array($result);
if ( ValidatePassword($password, $row['hash']) == true ) {
loginUser($email);
header("location: /spanel/index.php");
} else {
echo "<p>Login Failed.</p>";
}
これは、アカウントの作成時にパスワードのソルトとハッシュを生成するビットです。
function HashPassword($password)
{
$salt = bin2hex(mcrypt_create_iv(32, MCRYPT_DEV_URANDOM)); //get 256 random bits in hex
$hash = hash("sha256", $salt . $password); //prepend the salt, then hash
//store the salt and hash in the same string, so only 1 DB column is needed
$final = $salt . $hash;
return $final;
}
フィードバックをお寄せいただきありがとうございます。私の知識不足による問題が、攻撃の後ではなく、ここで見つかってよかったです。