本质是缓存键未携带用户唯一标识,导致多用户共享同一缓存项;必须在键中嵌入user_id或token哈希等上下文信息,禁用固定字符串,并在登出时清理对应键。

缓存键设计导致跨用户隐私泄露,本质是多个用户请求命中了同一个缓存项。问题不在“有没有缓存”,而在于“缓存键是否真正唯一标识了用户上下文”。排查要从生成、存储、读取、清理四个环节入手,聚焦“键是否携带足够区分度”。
检查缓存键是否嵌入用户唯一标识
这是最核心的一环。打开代码中所有生成缓存键的地方,确认是否显式包含 user_id、tenant_id 或 token 的哈希值(而非原始用户名、邮箱或 session ID)。 禁止出现以下写法:
-
"user:profile"(固定字符串,全站共用) -
"user_" + req.query.username(未过滤特殊字符,且用户名非唯一主键) -
"currentUser:data"(依赖全局变量,多线程/并发下极易错乱)
应统一使用结构化函数生成,例如:generateCacheKey("user_profile", { userId: 123, tenantId: "t456" }) → 返回 user_123:tenant_t456:profile。
验证缓存键在中间件与业务层是否一致
常见陷阱是:认证中间件提取了 req.user.id,但业务逻辑里又从 Cookie 或 Query 中重新解析用户身份,导致键不一致。
重点核对:
- 所有缓存写入(
SET)和读取(GET)是否都基于同一来源的用户 ID - JWT 场景下,是否每次都在请求入口解析 token 并校验签名,而不是信任未校验的 header 值
- 多租户系统中,
tenant_id是否随用户身份一同注入,且未被下游覆盖
上线前做交叉隔离测试
不能只测单用户流程。必须模拟真实并发场景:
- 用户 A 登录,调用
/api/user/profile,记录返回数据和 Redis 中生成的键(如user_1001:profile) - 用户 B 登录(不同设备或隐身窗口),调用相同接口,确认生成的是新键(如
user_1002:profile),且内容与 A 完全无关 - 用
redis-cli KEYS "user_*:profile"查看键列表,确认无重复、无通配冲突(如误存为user:profile)
建议在日志中开启缓存键生成 trace,例如输出 [CACHE] key=user_1001:profile, source=auth-middleware,便于故障时回溯。
检查登出与凭证失效后的清理机制
即使键本身正确,若用户登出后缓存未清除,后续同设备登录的新用户可能意外命中旧缓存(尤其在共享 Redis 实例、未设 namespace 的场景)。 必须确保:
- 登出接口中执行
DEL user_1001*或更精准的DEL user_1001:profile user_1001:settings - JWT 过期时,通过 Redis Key 过期事件(
__keyevent@0__:expired)触发关联键清理,或由定时任务扫描过期 token 对应的缓存 - 敏感数据(如余额、订单)设置较短 TTL(如 60s),降低残留风险











