ASP.NET Core:如何清除远程机器非当前会话缓存实现强制登出?
解决ASP.NET Core多设备登录时注销其他会话的问题
为什么Session ID与SQL Distributed Cache表的ID不匹配
SQL Distributed Cache不会直接存储原始Session ID,它会给会话键加上固定前缀(默认是Microsoft.AspNetCore.Session.Session-),然后对完整键做SHA256哈希处理,最终存储的ID列是哈希后的值,自然和你拿到的HttpContext.Session.Id不一致。
具体解决方案
建立用户与会话的关联表
新建一张UserSessions表,字段包含UserId(关联用户ID)、SessionKey(完整的缓存会话键,格式为Microsoft.AspNetCore.Session.Session-{SessionId})、CreatedAt(会话创建时间)。用户登录时,将当前会话的完整键和用户ID存入该表。生成匹配缓存表的哈希键(可选,直接用IDistributedCache更简便)
如果需要直接操作SQL缓存表,可以通过以下方法生成与表中ID一致的哈希值:using System.Security.Cryptography; using System.Text; public static string GenerateHashedCacheKey(string rawSessionKey) { using var sha256 = SHA256.Create(); var keyBytes = Encoding.UTF8.GetBytes(rawSessionKey); var hashBytes = sha256.ComputeHash(keyBytes); return Convert.ToBase64String(hashBytes); }传入完整的会话键(比如
Microsoft.AspNetCore.Session.Session-abc123),就能得到和缓存表ID列一致的值。注销其他设备的会话
当用户在新设备登录时,执行以下操作:- 从
UserSessions表中查询该用户所有会话键,排除当前会话的键; - 通过
IDistributedCache接口删除这些旧会话的缓存条目(底层会自动处理哈希匹配,无需直接操作数据库); - 清理
UserSessions表中对应的旧会话记录。
示例代码:
public async Task RevokeOtherUserSessions(string userId, string currentSessionId) { var currentSessionKey = $"Microsoft.AspNetCore.Session.Session-{currentSessionId}"; var otherSessionKeys = await _dbContext.UserSessions .Where(u => u.UserId == userId && u.SessionKey != currentSessionKey) .Select(u => u.SessionKey) .ToListAsync(); // 删除分布式缓存中的旧会话 foreach (var key in otherSessionKeys) { await _distributedCache.RemoveAsync(key); } // 清理关联表中的旧记录 await _dbContext.UserSessions .Where(u => u.UserId == userId && u.SessionKey != currentSessionKey) .ExecuteDeleteAsync(); }- 从
定期清理无效会话
配合Session的超时时间,用定时任务(如Hangfire)定期删除UserSessions表中过期的会话记录,避免数据冗余。
内容的提问来源于stack exchange,提问作者Robert Paulsen
相关产品推荐
相关产品推荐

