如何在ASP.NET中获取其他用户的ClaimsPrinciple?
问题解答
首先直接给两个核心问题的明确答复:
- 用户登出后,ASP.NET Core 认证框架默认不会持久化存储该用户对应的
ClaimsPrincipal对象 - 不存在框架自带的、可直接遍历访问所有用户
ClaimsPrincipal的全局存储,跨用户获取声明需要根据你的认证模式做对应实现,不要尝试直接访问其他用户的请求上下文绑定的ClaimsPrincipal实例。
关于登出后的ClaimsPrincipal存储逻辑
ClaimsPrincipal本质是绑定单次请求认证上下文的临时对象,不是全局常驻的内存实体:
- 用户登录成功后,每次请求抵达服务端时,认证中间件会从客户端携带的有效凭证(加密Cookie、JWT令牌载荷)反序列化构建当前请求对应的
ClaimsPrincipal,请求结束后该对象就会随上下文被回收。 - 登出操作的核心逻辑是作废客户端持有的认证凭证:比如Cookie认证会给客户端返回过期的同Key Cookie覆盖原有有效凭证,JWT场景通常由前端删除本地存储的Token。默认流程下服务端不会留存该用户的
ClaimsPrincipal对象。
特例:如果你手动实现了
ITicketStore将认证票据存在Redis/数据库等服务端存储,且登出时没有主动删除对应票据记录,那么票据中序列化的声明原始数据会留存到票据过期时间为止,但这不是ClaimsPrincipal对象本身的存储,只是构建该对象所需的原始数据。
跨用户获取声明/对应身份对象的正确实现
ClaimsPrincipal的设计定位是承载当前请求用户的身份信息,从来不是为跨用户访问设计的,不要尝试通过静态变量、全局上下文缓存等方式留存所有用户的ClaimsPrincipal实例,这类实现会面临内存泄漏、多实例部署数据不一致、对象已释放异常等问题。根据你的业务场景选对应方案即可:
方案1:仅需展示当前在线用户的声明
- 如果你用Cookie认证且接入了
ITicketStore做服务端会话存储,可以直接注入ITicketStore服务,通过你存储的会话关联Key(通常和用户Id绑定)拉取对应认证票据,手动重建ClaimsPrincipal:
// 从你的业务存储中查到对应用户的会话Key var targetUserSessionKey = GetUserSessionId(targetUserId); var authTicket = await _ticketStore.RetrieveAsync(targetUserSessionKey); if (authTicket != null) { var targetUserPrincipal = new ClaimsPrincipal(authTicket.Principal); // 遍历targetUserPrincipal.Claims即可拿到该在线用户的所有声明 }
- 如果你用JWT这类无状态认证,服务端默认不存任何在线用户的凭证信息,需要在用户登录成功时主动将该用户的声明列表关联用户Id存入缓存/数据库,需要展示时直接查询即可。
方案2:需要展示所有用户(含已登出、历史用户)的声明
这也是你做全局用户声明展示页面最推荐的方案:完全不要依赖认证体系的存储,直接从你的业务用户数据源查询。
所有声明对应的原始数据(角色、权限、个人标识等)本来就存在你的用户表、角色权限关联表等业务库中,直接查询数据后按需渲染即可,完全不受用户登录/登出状态影响,性能和稳定性都远高于依赖认证会话存储的方案。
内容的提问来源于stack exchange,提问作者user15961794
相关产品推荐
相关产品推荐

