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

时间:2013-11-28 15:15:40

标签: spring spring-security authorization roles

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

user1 - cat1 - ROLE_USER

user1 - cat2 - ROLE_EDITOR

类别不是静态的。可以添加新的和旧的删除。是否可以使用Spring Security实现这一目标?

4 个答案:

答案 0 :(得分:6)

从您的描述中,听起来像Spring Security为您提供的RBAC模型是不够的。您有2个选项可供选择。之一:

  1. 您可以通过实施自己的Access Decision Manager来自定义Spring Security(有关详细信息,请参阅here)或
  2. 您转移到基于属性的访问控制(也就是NIST here所解释的ABAC)。在Spring中使用ABAC的方法是使用可扩展访问控制标记语言XACML的Java实现。 XACML为您提供了一个外化的,基于策略和属性的授权框架。这意味着您可以定义策略,例如具有role = manager的用户可以在category = foo 中执行action = view的用户。您可以拥有任意数量的规则,并相应地组合/考虑它们。
  3. XACML for Java有几个开源和供应商实现:

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

    如果您想了解有关XACML的更多信息,我建议您查看其wikipedia页面以及包含供应商中立教程的YouTube channel

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

答案 1 :(得分:0)

我不知道你的“类别”是如何工作的,但你可以为UserDetails对象设置一个“角色”。

UserDetails对象具有Collection<? extends GrantedAuthority> getAuthorities();方法,“ROLE”值为GrantedAuthority.getAuthority()

因此,您可以将多个“ROLE”设置为单个会话。

您可以通过实施UserDetails控制您的UserDetailsService对象。

答案 2 :(得分:0)

我想我已经很晚了,但这对我有用:

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

@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
}

答案 3 :(得分:-1)

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

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

Spring安全性通过添加spring-acl jar来支持ACL。这是春季安全手册Acl部分的引用:

  

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

有关Spring安全ACL如何工作的详细信息,请参阅spring security manual部分16.1。这是关于如何使用Spring安全ACL的tutorial

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

但如果您的应用程序中经常使用此用例,则应考虑切换到ACL而不是RBAC,希望这会有所帮助。