PHP手册似乎没有提供检查给定session_id
是否存在的方法。例如,session_id()
有一个可选的id
参数,但它会替换现有的id
而不是查找所需的方法:session_id_exists(some-id)
为什么我需要检查给定的session_id
是否存在?用例是一种体育订阅服务,其中密码共享已成为一个问题。在登录时,我将用户的会话ID存储在数据库中,并使用它来与附加到给定userID
的任何其他现有会话ID进行比较。
为了实现,我需要检查当前会话中是否存在收集的会话ID(密码共享的证明是同时登录多个用户)。
我认为有一种简单的方法可以实现这一目标......
答案 0 :(得分:3)
你如何在index.php
的顶部做这样的事情// Update current userid/session record with current timestamp
mysql_query("UPDATE sessions SET last_activity = CURRENT_TIMESTAMP() WHERE user = '$username' AND sid = '".session_id()."'");
// Search for multiple records with timestamp in the last 20 minutes where user id is the same
$result = mysql_fetch_assoc(mysql_query("SELECT COUNT(*) AS current_sessions FROM sessions WHERE user = '$username' AND last_activity > '".date('Y-m-d H:i:s', time() - 1200)."'"));
if ($result['current_sessions'] > 1) {
// handle duplicates here
}
您可能不喜欢这种方法,因为它在每次页面加载时都涉及两个数据库查询,但它应该可以工作,并且可能比检查会话文件更有效。
答案 1 :(得分:0)
遵循CodeCaster的评论:
对于每个用户连接/断开连接,而不是检查PHP会话ID。会话到期,维护当前连接用户的列表(以及连接时间,IP等),例如在数据库表中。
因此,您将能够使用单个帐户检测多个连接。
您也可以尝试创建一个循环遍历所有会话文件的小脚本(如果您使用默认存储),请使用' unserialize()'在它上面并检查几个会话文件是否具有相同的用户标识符(假设您将它们存储到$_SESSION
)
编辑:由于这应该针对每个用户连接进行,因此数据库表方法(如CodeCaster建议的那样)似乎更好。
答案 2 :(得分:0)
您应该创建自己的会话状态实现,为您的用例提供所需操作的界面。
class SessionState
{
public function idExists($id)
{
$gateway = new SessionGateway();
$result = $gateways->searchById($id);
# ...
}
}
如果您已经实现了详细信息,则只需使用应用程序中的对象即可。
答案 3 :(得分:0)
首先,这对防止密码共享的方法进行了很好的探索。
我根据每个请求跟踪用户活动的直觉反应(即@DaveRandom提出的2个查询解决方案)是啊啊,不!正如@CodeCaster指出的那样,可能是过早优化的情况,但是,嘿,我们有一个小的(几千)但狂热的用户群,对于曲棍球赛季的开始和比赛结果来说非常随意。这个网站有多年来一直运行不稳定,不想摇摇欲坠,这是一项付费服务,所以表现一定非常出色。
好的,解决方案:
apache用户对会话目录中的会话文件具有读/写访问权限。通过在登录时记录session_id,我们可以锁定共享密码帐户。成功登录后:
- Loop through stored session ids related to target account
- if /path/to/session-id-file not empty, increment login counter
- if login counter exceeds number of users allowed for a given plan:
- delete all session files related to target account
- lock the account and force a password reset
最小的开销,实施是蛋糕,问题解决了。
注意:我原本以为没有创建安全循环就无法访问会话目录文件;然而,事实并非如此(至少在我的CentOS 5版本中)。您无法获得与当前用户的会话无关的session_id,但您可以存储给定用户的会话ID,并且从任何用户的会话中访问存储其会话的会话文件(包括吹走文件)。关键是要使用会话ID来查找相应的/ path / to / session-file