Redis作为会话存储,使一个用户的所有会话无效化

8
我将使用Redis作为会话存储,将会话存储如下:
[NameSpace]:[UniqueId] -> [email_id]

以下是问题:

当用户重置密码时,如何使该用户的所有会话无效?

以下是我想出的解决方案

将电子邮件 ID 存储为 UID 的一部分

将会话存储如下

[NameSpace]:[UniqueId]-[email_id] -> [email_id]

当用户重置密码时,我可以使用SCAN MATCH删除所有键。

维护UID列表

存储会话后,可以维护一个UID列表

[NameSpace]:[UniqueId] -> [email_id]

维护一个独立的列表

[NameSpace2]:[email_id] -> [ "[UniqueId]", "[UniqueId]" ]

并使用列表使会话失效。(我可以使用redis命名空间pubsub来维护上述列表的有效性)

我的问题是:

  1. 在redis中进行批量会话失效的推荐方法是什么?
  2. 将会话ID存储为[UniqueId]-[email_id]这样的方式在cookie中存在安全问题吗?

PS:我知道有一个类似的问题,但我觉得它很嘈杂,并且更适用于express.js而不是redis和用户会话的通用问题。 (在express.js中使单个用户的所有会话无效)

3个回答

3

维护所有用户会话的集合。

[NameSpace]:[email_id] -> {}

每个会话标识符是集合中的一个值。如果您想存储会话属性,请使用映射 sessionIdentifier1 -> sessionProperties1(查找和删除成本相同)。

[NameSpace]:[email_id] -> {sessionIdentifier1 , sessionIdentifier2}

批量会话失效 - 删除[NameSpace]:[email_id]。成本为 O(1)。

查找会话标识符 - 在键 [NameSpace]:[email_id] 上使用SISMEMBER查找sessionIdentifier1。成本为 O(1)。

将会话ID像 [UniqueId]-[email_id] 存储在 cookie 中是否存在安全问题?

这取决于情况。如果 cookie 不是 HttpOnly,那么它将允许恶意 JS 通过 XSS 漏洞读取该 cookie。您可能会面临钓鱼攻击的风险。您可以使用用户内部的 UUID 代替。


1

关于第一点 - 由于活跃用户会话的数量远低于数据库中总会话数(大概),我建议手动管理每个用户的活跃会话,而不是进行 SCAN 操作。然而,我会为每个用户使用一个集合来存储活跃会话的键标识符,而不是列表,因为你希望能够有效地添加和删除活跃会话。如果用户有很多需要批量失效的活跃会话,则可以使用 SSCAN 而不是 SMEMBERS。

关于第二点 - 如果有人进入了您的应用程序/数据库服务器,那么存在许多安全问题 :)


还有一些更多的细节在这里:https://groups.google.com/d/msg/redis-db/Vm7c4gvXgl8/vdRw-z1YuxgJ - Itamar Haber
1
谢谢你的回答,我会和我的团队讨论。就你的第二个答案而言,如果有人进入了应用程序/数据库服务器,我们无论如何都完蛋了,他们可以读取密钥和值。所以这应该不是一个问题。 - Gautam

1

根据您的示例,看起来您将会话存储为键值对,而用户可以有多个会话。您可以通过几种方式来处理这种情况。

  1. 在页面加载时使用非常短的过期时间和刷新时间。在更改密码代码的一部分中,您从用户会话中提取会话ID并将其删除。短暂的过期时间确保旧会话被删除。

  2. 使用哈希或一组哈希值。根据用户数量,如果用户基数“较小”,则可以使用单个哈希,或者将它们哈希成桶。然后,您可以存储命名空间:sessions [userid] -> email以进行会话。此时,您可以轻松删除单个用户会话,并且不会有重复会话。但您会失去自动过期会话的功能。

  3. 使用哈希,排序集和定时任务进行清理。在此方法中,您将会话ID用作哈希键,该哈希具有会话键及其值。其中两个成员是创建和最后查看的时间戳。然后,您可以为每个用户使用另一个哈希来将sessionid映射到最后查看的时间戳。通过这种方式,您可以保持选项1上的页面刷新更新,但是您可以轻松地获取每个用户的会话列表。但是,这样做不能修剪旧会话。您可以过期哈希表,但必须在页面视图上同时过期和更新两个,或者使用定时任务。

您可以使用排序集合,其中会话ID为成员,时间戳为分数。现在,您可以使用标准的排序集合查询,例如zrangebyscore,将所有早于某个时间戳的会话获取到列表中,然后删除这些键和成员。
您可以通过使会话创建代码检查用户的会话哈希是否存在,并使用过期或让会话创建代码检查上次更新是否符合您的活动会话标准并重复使用它或清除其瞬态成员来防止多个会话。因为您只有一个会话或可以轻松地获取列表,并且希望具有过期和/或计划任务来修剪旧会话,所以管理会话变得更加容易 - 无需扫描或键。
我建议每个用户只使用单个会话,并自由使用过期。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接