检测session_id(some-id)是否存在

发布于 2024-12-16 23:14:04 字数 600 浏览 1 评论 0原文

可能的重复:
检测 PHP 会话是否存在

PHP 手册似乎没有提供检查是否存在的方法给定的 session_id 存在。例如,session_id() 有一个可选的 id 参数,但它会替换现有的 id,而不是按照所需的方法进行查找: session_id_exists(some-id)

为什么我需要检查给定的 session_id 是否存在?使用案例是体育订阅服务,其中密码共享已成为问题。登录时,我将用户的会话 ID 存储在数据库中,并使用它与附加到给定 userID 的任何其他现有会话 ID 进行比较。

为了实现,我需要检查当前会话中是否存在收集的会话ID(密码共享的证明是多个用户同时登录)。

我认为有一个简单的方法可以实现这一目标......

Possible Duplicate:
Detect if PHP session exists

The PHP manual does not seem to provide a means to check whether a given session_id exists. For example, session_id() has an optional id param, but that replaces the existing id as opposed to doing a lookup a la desired method: session_id_exists(some-id)

Why do I need to check whether a given session_id exists? Use case is a sports subscription service where password sharing has become a problem. On login I am storing the user's session id in DB and using that to compare against any other existing session id(s) attached to a given userID.

In order to implement, I need to check whether collected session ids exist in current session (the proof of password sharing being more than one user logged in at the same time).

I assume there's an easy way to achieve this...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

对你再特殊 2024-12-23 23:14:04

// 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
}

可能不喜欢这种方法,因为它在每个页面加载时涉及两个数据库查询,但它应该可以工作,并且可能比检查会话文件更有效。

How about you do something like this at the top of 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
}

You may not like this approach as it involves two DB queries at every page load, but it should work and would probably be more efficient than checking the session files.

骷髅 2024-12-23 23:14:04

按照 CodeCaster 的评论:

对于每个用户连接/断开连接,您应该检查 PHP 会话 ID,而不是检查 PHP 会话 ID。会话过期,维护当前连接的用户列表(可能还有连接时间、IP 等),例如在数据库表中。

因此,您将能够检测单个帐户的多个连接。

您也可以尝试创建一个循环所有会话文件的小脚本(如果您使用默认存储),对其使用“unserialize()”并检查多个会话文件是否具有相同的用户标识符(前提是您存储它们)到 $_SESSION

编辑:由于应该为每个用户连接执行此操作,因此数据库表方法(如 CodeCaster 建议的那样)似乎更好。

Following CodeCaster's comment:

Instead of checking PHP session IDs, you should, for each user connexion/disconnection & session expiration, maintain a list of currently connected users (along with connection time, IP etc. maybe), for example in a DB table.

Thus you will be able to detect multiple connections with a single account.

You can as well try to create a small script looping over all session files (if you use the default storage), use an 'unserialize()' on it and check if several session files have the same user identifiers (provided that you store them into $_SESSION)

EDIT: since this should be done for each user connection, the DB table approach (like what CodeCaster suggests) seems better.

荒岛晴空 2024-12-23 23:14:04

您应该创建自己的会话状态实现,为您的用例所需的操作提供接口。

class SessionState
{
    public function idExists($id)
    {
        $gateway = new SessionGateway();
        $result = $gateways->searchById($id);
        # ... 
    }
}

如果您已经实现了详细信息,则可以在应用程序中使用这些对象。

You should create your own Session State implementation that offers an interface for the action(s) you need to have for your use-case.

class SessionState
{
    public function idExists($id)
    {
        $gateway = new SessionGateway();
        $result = $gateways->searchById($id);
        # ... 
    }
}

If you have implemented the details, you can just use the object(s) within your application.

烈酒灼喉 2024-12-23 23:14:04

首先,这是对防止密码共享的方法的一次很好的探索。

我对基于每个请求跟踪用户活动(即 @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

First of all, this has been a nice exploration of ways to prevent password sharing.

My gut reaction to tracking user activity on a per request basis (i.e. the 2 query solution proposed by @DaveRandom) was ahhhhh, no! As @CodeCaster points out, a likely case of premature optimization, but hey, we have a small (few thousand) but rabid user base that will be very click-happy with the start of hockey season and game results coming in. The site has been running snappily for years, don't want to rock the boat, this is a paid service, so performance must be excellent.

OK, the solution:

The apache user has read/write access to the session files in the session directory. By recording session_id at time of login, we have the ingredients to lock down shared password accounts. On successful login:

- 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

There is minimal overhead, the implementation is cake, problem solved.

Note: I had originally thought it was impossible to access the session directory files without creating a security loop; however, that is not the case (at least in my stock CentOS 5 setup). You cannot get a session_id not related to the current user's session, but you can store a given user's session id and access the session file that stores their session from any user's session (including blowing away the file). The key is having the session id to lookup the corresponding /path/to/session-file

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文