我有一个分类广告网站,我正在创建一个登录系统...
在下面的代码中,提交了一个包含“用户名”和“密码”的表单。此外,还有“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是否已设置而不是检查会话?
答案 0 :(得分:2)
登录是关于安全性的;看来安全总是比较困难。
您可以在代码中改进一些事项。第一:
密码的安全性取决于哈希算法的强度。您选择使用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
}
(更好)
使用经过验证的库来获取密码哈希的东西,看一下:Portable PHP password hashing framework并尝试使用CRYPT_BLOWFISH算法(如果完全可以的话)。
<强>第二强>
您应该只将会话密钥存储在会话cookie中。所有其他信息都存储在服务器上
会话cookie已经通过PHP的session_start()函数调用发出,因此您不必再担心这一点。
如果要检查会话生存期,则应将此信息存储在会话数组中:
$_SESSION['lastActivity'] = time()+60*60*24*100;
<强>第三强>
记住我的令牌是一个'密码等效',所以你应该只在你的数据库中存储一个令牌的哈希值,只是把它当作一个密码,只有这个'密码'不是用户输入的,而是从cookie中读取的。 / p>
答案 1 :(得分:1)
散列的全部意义在于它是不可逆的,所以它并没有像你用来记忆我的函数那样添加任何值。停止假装它做任何有用的事情,并使用随机令牌记住我(并在数据库中记录这个用户名)然后,如果你得到一个客户端呈现一个记住我没有经过身份验证的会话的cookie,你知道在哪里寻找找出它是谁。
(这也允许在用户继续移动到不同机器的地方应用合理的方法 - 您可以说保留最后2个值 - 并在他们试图从第3台机器上记住我时标记。)
100天的超时时间相当长 - 可能是30天(自动刷新可能更合适,具体取决于风险等级。