如何通过上下文更改Spring Security角色



我想知道是否可以根据所选类别设置角色。在我们的应用程序中,有一些类别包含文章。现在我们有了一个类似的角色层次结构:ROLE_ADMIN > ROLE_EDITOR > ROLE_USER。问题是,根据当前选择的类别,用户可能有不同的角色:

user1 - cat1 - ROLE_USER
user1 - cat2 - ROLE_EDITOR

这些类别不是静态的。可以添加新的,也可以删除旧的。是否可以使用Spring Security实现这一点?

根据您的描述,听起来Spring Security提供的RBAC模型还不够。您有两个选项可供选择。任一:

  1. 您可以通过实现自己的Access Decision Manager来自定义Spring Security(有关详细信息,请参阅此处)或
  2. 您将转向基于属性的访问控制(又称ABAC,由NIST在此处解释)。在Spring中使用ABAC的方法是使用XACML的Java实现,即可扩展访问控制标记语言。XACML为您提供了一个外部化的、基于策略和属性的授权框架。这意味着您可以定义策略,例如角色=管理器的用户可以在category=foo中执行action=view。你可以有任意多的规则,并相应地组合/因子

Java的XACML有几个开源和供应商实现:

  • SunXACML
  • HerasAF
  • IBM
  • Axiomatics(免责声明:我工作的供应商)

如果你想了解更多关于XACML的信息,我建议你查看它的维基百科页面以及我们的YouTube频道,该频道提供了与供应商无关的教程。

XACML可能对您的用例来说太多了,但它仍然值得考虑。

我觉得我来晚了一点,但这对我来说很有效:

选择新类别后,可以在会话中设置具有新角色的新身份验证对象(以前的身份验证对象将失效)。类似这样的东西:

@RequestMapping(value = "/cat1")
String cat1(HttpServletRequest request) {
    reloadRolesForAuthenticatedUser("cat1")
    ....
}
private void reloadRolesForAuthenticatedUser(String cat) {
    Authentication auth = SecurityContextHolder.getContext().getAuthentication()
    List<String> newRoles = getRoles(auth.getPrincipal().getUsername(), cat)
    List<GrantedAuthority> authorities = getAuthorities(newRoles)
    Authentication newAuth = new UsernamePasswordAuthenticationToken(auth.getPrincipal(),auth.getCredentials(),authorities)
    SecurityContextHolder.getContext().setAuthentication(newAuth)
}

private List<GrantedAuthority> getAuthorities(List<String> roles) {
    List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>()
    if (!roles.isEmpty()) {
        for (String r : roles) {
            auths.add(new SimpleGrantedAuthority(r))
        }
    }
    return auths
}

我不知道您的"类别"是如何工作的,但您可以将"ROLE"设置为UserDetails对象。

UserDetails对象具有Collection<? extends GrantedAuthority> getAuthorities();方法,"ROLE"是GrantedAuthority.getAuthority()的值。

因此,您可以将多个"角色"设置为一个会话。

并且您可以通过实现UserDetailsService来控制您的UserDetails对象。

此用例不能使用默认的基于角色的访问控制(RBAC)功能来完成,因为用户权限在运行时会根据与用户相关的一些数据动态更改。

这实际上是为访问控制列表(ACL)设计的用例。

Spring security通过添加Spring-acl-jar来支持acl。这是引用弹簧安全手册Acl部分:

复杂的应用程序通常会发现需要定义访问权限,而不仅仅是在web请求或方法调用级别。安全决策需要包括谁(认证),where(MethodInvocation)和what(SomeDomainObject)。换句话说,授权决策还需要考虑方法调用的实际域对象实例主题。

有关spring安全ACL如何工作的详细信息,请参阅spring安全手册第16.1节。这是一个关于如何使用Spring安全ACL的教程。

但是Spring ACL意味着4个额外的数据库表等,所以如果这是应用程序中唯一的情况,那么最好创建一个带有一些harcode规则的自定义决策管理器。

但是,如果这种用例在您的应用程序中很常见,您应该考虑切换到ACL而不是RBAC,希望这会有所帮助。

最新更新