【发布时间】:2026-02-23 05:50:01
【问题描述】:
我一直在研究这个用于用户登录的身份验证系统,希望得到一些反馈。
我的想法是这样的。使用会话和一个额外的 cookie。会话 cookie 和附加 cookie 一起工作。在我的 Login 类中,检查用户名和密码是否正确后,我调用 sessionStart 方法并从数据库发送用户 ID:
public function sessionStart($id) {
session_start();
$cookieName = "RagingBull";
$hash = $this->loginHash($id);
setcookie($cookieName, $hash);
}
在我的 sessionStart 方法中,调用了一个 loginHash 方法。 loginHash 方法创建哈希并将会话 cookie 和附加 cookie 链接在一起。
public function loginHash($id) {
$timeStamp = time();
$randNumber = mt_rand(0, 1000);
$userId = $id;
$_SESSION['timeStamp'] = $timeStamp;
$_SESSION['randNumber'] = $randNumber;
$_SESSION['userId'] = $id;
$userAgent = $_SERVER['HTTP_USER_AGENT'];
$salt = "On the Waterfront";
$ipFrag = substr($this->getUserIP(), 0, 5);
$forHash = $timeStamp.$salt.$userId.$ipFrag.$randNumber.$userAgent;
$hash = md5($forHash);
return $hash;
}
为了创建哈希值,我使用
- timeStamp,也保存在会话cookie中
- randNumber,保存在会话cookie中
- userId,保存在会话cookie中
- 用户代理,
- salt,保存在服务器内部
- ipFrag,只是用户IP地址的一个片段。
我在会话 cookie 中保存了一些值,以便稍后在创建哈希值进行比较时使用它们。之后,我们回到 sessionStart 方法,并使用返回的哈希值创建额外的 cookie,然后用户登录。
对于身份验证,我有 Session 类。
class Session {
public function __construct() {
session_start();
// checks to see if all the cookies are there
if(!isset($_SESSION['userId']) || !isset($_COOKIE['RagingBull'])) {
header("Location:http://localhost/login.php");
}
//create hash for comparison
$hash = $this->loginHash();
//if hashes are not the same, redirect
if(strcmp($hash, $_COOKIE['RagingBull']) !== 0) {
header("Location:http://localhost/login.php");
}
}
public function loginHash() {
$timeStamp = $_SESSION['timeStamp'];
$randNumber = $_SESSION['randNumber'];
$userId = $_SESSION['userId'];
$userAgent = $_SERVER['HTTP_USER_AGENT'];
$salt = "On the Waterfront";
$ipFrag = substr($this->getUserIP(), 0, 5);
$forHash = $timeStamp.$salt.$userId.$ipFrag.$randNumber.$userAgent;
$hash = md5($forHash);
return $hash;
}
public function getUserIP() {
if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
$ip = $_SERVER['HTTP_CLIENT_IP'];
} elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
$ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else {
$ip = $_SERVER['REMOTE_ADDR'];
}
return $ip;
}
}
要使用它,我只需创建 Session 类的实例。然后,在构造函数中,在基本检查之后,创建哈希进行比较,我使用之前保存的会话 cookie 中的 timeStamp、userId 和 randNumber,并将它们与请求页面的用户的用户代理和 ip 片段结合起来。
- 是否存在明显的安全或逻辑缺陷?
- 是否足够安全?
- 对于每个页面请求,服务器是否有太多工作要做?
- 这些都是不必要的吗?
【问题讨论】:
-
请不要自己滚动密码散列,特别是不使用 MD5()。 PHP 提供
password_hash()和password_verify()请使用它们。这里有一些good ideas about passwords如果你使用的是5.5之前的PHP版本there is a compatibility pack available here -
回答您的问题:1) 是的。 2) 没有 3) 大部分是不必要的 4) 是的
-
我能做到。在将密码存储在数据库中并检查它们时,我使用了 password_hash() 和 password_verify()。但我在这里只使用了 md5,因为它不是关于密码,而是关于登录后身份验证的哈希。
-
Surley 用户登录后,您知道他们已通过身份验证,因为您在他们的会话中有帐户参考
-
@RiggsFolly ,好吧,你有时间再解释一下吗?我真的很感激。我认为通过这种方式,攻击者通过暴力攻击简单地猜测有效的会话会话密钥和额外的 cookie 密钥会有点困难。当然,我会重新生成会话 ID 和 cookie 密钥以防止会话固定。
标签: php security session authentication cookies