Spring安全:设置授予权限

36
有没有办法在Authentication/UserDetailsImpl对象中设置List<GrantedAuthority>?在我的应用程序中,我有两个安全层,一个用于登录(使用自定义的登录认证器,在该类中使用UsernamePasswordAuthenticationToken设置Authentication对象),另一个用于“挑战问题”,用户会被提示回答特定的问题。

我的目的是在用户回答挑战问题后,将GrantedAuthority添加到当前已创建的List<GrantedAuthority>中(在登录过程中创建)。

这可能吗?

需要澄清的一件事是UserDetails实现属于哪个类。Spring没有名为UserDetailsImpl的类。JdbcDaoImpl创建一个User类的实例,而LDAP版本创建一个LdapUserDetailsImpl的实例。因此,它非常依赖于您获取的对象类型,您是否可以更改权限。我从未真正使用过Spring提供的UserDetails实现,正是因为像授予权限的不可变集这样的东西是可能会改变的。 - Spanky Quigman
2个回答

43

你可以使用以下代码完成它:

Collection<SimpleGrantedAuthority> oldAuthorities = (Collection<SimpleGrantedAuthority>)SecurityContextHolder.getContext().getAuthentication().getAuthorities();
SimpleGrantedAuthority authority = new SimpleGrantedAuthority("ROLE_ANOTHER");
List<SimpleGrantedAuthority> updatedAuthorities = new ArrayList<SimpleGrantedAuthority>();
updatedAuthorities.add(authority);
updatedAuthorities.addAll(oldAuthorities);

SecurityContextHolder.getContext().setAuthentication(
        new UsernamePasswordAuthenticationToken(
                SecurityContextHolder.getContext().getAuthentication().getPrincipal(),
                SecurityContextHolder.getContext().getAuthentication().getCredentials(),
                updatedAuthorities)
);

4
遗憾的是,只有当您知道安全上下文中存在的身份验证类型时,它才能起作用,在这种情况下是用户名密码身份验证令牌(UsernamePasswordAuthenticationToken)。 - John B
这只会更改上下文中的权限,而不是上下文的主体。如果您尝试通过SecurityContextHolder.getContext().getAuthentication().getPrincipal().getAuthorities()获取权限,则不会出现更新后的权限。您需要将这些权限设置为新的主体,然后在设置身份验证构造函数时使用它。 - gerard

-5

UserDetails.getAuthorities() 方法只返回一个 Collection<GrantedAuthority> 对象。您可以使用适当的 Collection 方法将新权限添加到该集合中。

Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
    ((UserDetails) principal).getAuthorities().add(New GrantedAuthorityImpl("ROLE_FOO"));
}

塞拉。


4
无法添加到收藏 -> UnmodifiableCollection - Slavak
@Slavak 这真的取决于您在UserDetails中使用的实现方式。我们的实现中没有使用org.springframework.security.core.userdetails中的User类。显然,如果您需要设置或修改权限,并且使用的实现中集合是不可变的且没有setAuthorities()方法(这不是UserDetails接口承诺的),那么问题的答案就是不可能的。否则,您必须提供自己的UserDetails实现,这也是大多数灵活的应用程序需要做的事情。 - Spanky Quigman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接