![](/img/trans.png)
[英]Is this safe enough for user login and verification? (PHP, MySQL, Sessions)
[英]New to PHP logins and sessions; Is this safe enough?
我有一個分類網站,我正在為...創建登錄系統。
在下面的代碼中,具有“用戶名”和“密碼”的表單已提交到。 還提供了“ remember_me”功能(代碼尚未經過測試):
else if($row['password']===$pass){
session_start();
$_SESSION['logged_in'] = '1';
$remember_me = isset($_POST['remember']) ? $_POST['remember'] : '0';
if($remember_me=='1'){
$text = "SECRET_TEXT_AND_NUMBERS_HERE";
$username= $row['username'];
$salt1 = sha1($row['alt_username']);
$salt2 = sha1($text);
$cookie_value = $salt1.':'.$username.':'.sha1($row['alt_username'].$salt2.$salt1);
setcookie("s_b", $cookie_value, time()+60*60*24*100, "/");
}
}
現在,此代碼是登錄頁面的良好起點嗎?
此外,這是一個重要的后續問題,如果用戶希望保持登錄狀態,那么我是否要像代碼中那樣設置$_SESSION
變量,然后檢查是否在頁面上所有頁面的開頭都設置了該變量?現場?
if(isset($_SESSION['logged_in'])) // Then user is logged in already
還是要檢查是否設置了在登錄頁面中創建的cookie,而不是檢查會話?
登錄是關於安全性; 安全總是比看起來要困難的多。
您可以在代碼中進行一些改進。 第一:
密碼的安全性在於hasing算法的優勢。 您選擇使用sha1
(比md5更好,但是如果使用PHP版本> = 5.3,則可以通過使用sha256或bCrypt進行改進)
第一
您使用的鹽應該是隨機值,與散列結果一起存儲。 換句話說,要存儲在數據庫中的值是:
$salt = [some random string of predifend lenght]; // Let's say 16 characters in length
$storedValue = $salt . sha256($salt . $password);
您檢查密碼:
if ($row['username'] == $_POST['username'] && substr($row['$storedValue'], 16) == sha256(substr($row['$storedValue'], 0, 16) . $_POST['password'])) {
// login ok
} else {
// login fail
}
(更好)
使用經過驗證的密碼哈希庫,看看: 可移植的PHP密碼哈希框架,並嘗試使用CRYPT_BLOWFISH算法(如果可能的話)。
第二
您應該只將會話密鑰存儲在會話cookie中。 所有其他信息都存儲在服務器上。
會話cookie已經通過PHP的session_start()函數調用發出,因此您不必再為此擔心。
如果要檢查會話的生存期,則應將此信息存儲在會話數組中:
$_SESSION['lastActivity'] = time()+60*60*24*100;
第三
“記住我”令牌是等效的“密碼”,因此您應該只將令牌的哈希存儲在數據庫中,僅將其視為密碼,用戶不會鍵入此“密碼”,而是從cookie中讀取。
哈希的全部要點在於它不可逆,因此它並沒有真正像您使用“記住我”功能那樣增加任何價值。 停止假裝它會做任何有用的事情,並使用一個隨機令牌作為“記住我”(並使用用戶名將該日志記錄在數據庫中),然后,如果您得到的客戶端在沒有經過身份驗證的會話的情況下顯示“記住我” cookie,那么您將知道在哪里找出是誰。
(這還允許在用戶不斷移動到其他機器上時使用一種明智的方法-您可以說保留最后2個值-並且在他們嘗試從第三台機器記住我時進行標記)。
100天的超時時間很長-可能是30天(根據風險級別,自動刷新可能更合適。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.