我正在使用 Spring Security 为我的 webapp 提供身份验证和授权。
我使用标准方法UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
使用DaoAuthenticationProvider
.
成功登录后,我可以通过两种不同的方式访问用户的权限:
1#SecurityContextHolder.getContext().getAuthentication().getAuthorities()
2#((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getAuthorities()
它们应该是相同的,因为 Authentication 实例权限列表是从 UserDetails 的 user.getAuthorities() 构造的,但它们实际上是 2 个不同的 Collection 实例。主体的一个是 UnmodifiableSet,Authentication 实例中的一个是 UnmodifiableRandomAccessList。2 个不同的 Collection 实例,它们包含相同的权限列表。
当我试图找到一种解决方案来动态地向当前经过身份验证的委托人添加权限时,这让我感到震惊。这不是一件好事,安全层不应该允许我这样做,但这仍然是我需要的。
我发现可以接受的一个解决方案是使用当前经过身份验证的用户以编程方式登录
new UsernamePasswordAuthenticationToken(authentication.getPrincipal(), authentication.getCredentials(), dbAuthsSet);
authentication
是当前的身份验证实例和dbAuthSet
当前的权限列表+我需要添加的一个。
这很好用。现在唯一奇怪的是
1#SecurityContextHolder.getContext().getAuthentication().getAuthorities()
2#((UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getAuthorities()
不再返回相同的权限列表。
如果我根据我的应用程序中的身份验证列表检查权限,我很好,这是完全合理的事情。但是如果我检查校长的名单,我就会面临不一致的问题。
你怎么看?这是一个应该在 Spring 的 Security 3.2 中解决的问题吗?
您是否认为以编程方式登录new UsernamePasswordAuthenticationToken()
以实现我的目标,即向当前经过身份验证的用户授予会话的额外权限是合理的?
使用 Spring 的Run-As 身份验证替换功能是否是一个好案例?有人可以分享这方面的经验吗?