假设我有3个用户登录到我的应用程序,一个管理员用户和2个普通用户,他们共享一组权限,这些权限被转换为角色,例如,他们每个人都有ROLE_EDIT
,ROLE_ADD
和ROLE_DELETE
。
在登录时,管理员用户进入并从他们的共享权限集中删除一个角色,假设该权限集从ROLE_EDIT, ROLE_ADD, ROLE_DELETE
变为ROLE_EDIT, ROLE_ADD
。我们现在希望从当前登录的两个用户中删除ROLE_DELETE
角色。
我知道SecurityContextHolder
是线程范围的,所以只有管理员用户的信息。有没有一种简单的方法可以访问当前登录的2个用户的身份验证信息,以便我可以删除该角色,而不必强制他们注销并重新登录?
2条答案
按热度按时间cedebl8k1#
默认情况下,
SecurityContext
将存储在HTTP会话中的SPRING_SECURITY_CONTEXT
项下(由SecurityContextHolderFilter
处理,并进一步委托给HttpSessionSecurityContextRepository
)。这意味着理论上您可以首先为需要更新其角色的用户获取HttpSession
,然后从中获取他的SecurityContext
并进行更新。遗憾的是Servlet不提供API来通过会话ID获取HTTP会话,但您可以参考this idea手动跟踪会话和用户ID之间的Map。或者检查Web容器是否提供API来做到这一点。
vu8f3i0k2#
根据您的问题,我理解您正在尝试为用户构建一个动态角色模型,而无需再次登录。为所有登录用户重写角色的想法是不可能的,因为用户会话不可用,这种不可用是安全性的一部分,并且可以在任何用户请求期间由匹配JSESSIONID的服务器绑定。这就是为什么您在
SecurityContextHolder
中只有管理员信息。如果我们理解了SecurityContextHolder
是如何变得可用的,我们可以看到这个对象是通过Spring Security Filter Chain bean构建的,并且这个对象的数据是从当前用户会话中获取的。为了更新用户角色,我们可以实现相同的Spring Security Filter Chain组件(让我们像RoleRecalculationRequestFilter
一样调用),它可以在构建SecurityContextHolder
的组件之后集成,然后基于SecurityContextHolder
中的信息,我们可以从任何资源加载更新的角色(数据库,内存存储等)基于SecurityContextHolder
中的信息,然后将更新的角色列表设置到SecurityContextHolder
对象中,该操作将对每个请求执行,因此您的用户始终将在上下文中拥有最新的角色。