(请注意,虽然这里的技术仍然有些有效;PHP 示例不应逐字复制,因为有更安全的方法可以将用户提供的值合并到 SQL 查询中)
与其存储用户是否处于活动\非活动状态,不如存储一些可以针对每个操作检查用户的属性;例如,每次用户尝试执行需要身份验证的操作时,它都会在继续之前检查该属性是否匹配。
我建议您执行以下操作;
首先,创建一个哈希值,以便在用户登录时唯一标识用户。我想sha1 http://php.net/manual/en/function.sha1.php of time() http://php.net/manual/en/function.time.php足以避免碰撞。无论您选择什么,请确保它足够多样化,以便其他登录用户收到相同哈希值的机会极低(例如,不要对 IP 地址或浏览器的用户代理进行哈希处理,因为这些内容并没有变化)足够的)。
其次,将此哈希值存储在您的数据库和用户的数据库中session http://www.php.net/manual/en/book.session.php这样做会有效地“注销”以前的用户,因为每次有人登录时哈希值都应该不同。
由于我们使用会话,因此应自动将 cookie 放置在用户的浏览器中,该浏览器将包含一个唯一 ID,用于识别用户的会话数据。 cookie 的内容并不是真正值得关注的。
接下来,创建一个名为的函数authenticateUser()
或类似的,它将在每个脚本开始时调用,以确保用户经过身份验证。此脚本应查询数据库,检查具有您的用户 ID 的用户是否具有与您的用户的哈希相匹配的哈希。
例如:
function authenticateUser($id, $hash, $databaseLink) {
# SQL
$sql = 'SELECT EXISTS(
SELECT 1
FROM `tbl_users`
WHERE `id` = \''.mysql_real_escape_string($id).'\'
AND `hash` = \''.mysql_real_escape_string($hash).'\'
LIMIT 1
);';
# Run Query
if ($query = mysql_query($sql, $databaseLink)) {
# Get the first row of the results
# Assuming 'id' is your primary key, there
# should only ever be one row anyway.
$result = mysql_fetch_row($query);
# Casting to boolean isn't strictly necessary here
# its included to indicate the mysql result should
# only ever been 1 or 0.
return (bool)($result[0]);
} else {
# Query error :(
return false;
}
}
然后,我们只需通过authenticateUser()
用户的ID
, hash
(根据您的会话数据)和database link
(对于数据库连接,您必须提前打开)。
If authenticateUser()
回报true
,用户已通过身份验证。如果false
、用户不存在或数据库不可用或存在 SQL 错误。
但请注意,这会增加您的服务器负载,因为每个页面请求都会发送一次数据库请求。在任何特定时间都有数千人登录的大型项目上这样做可能不太明智。我确信有人可以提出改进建议。
此外,等待 cookie 过期并不是强制不活动的用户注销的最佳方法,因为您永远不应该信任 cookie。相反,您可以添加一个名为last_active
您可以在每次用户通过身份验证时更新它。这也会增加服务器负载,但允许您通过删除hash
对于例如 3 小时不活动的用户。