Spring Security和ABAC(基于属性的访问控制)

时间:2015-08-14 07:40:12

标签: spring-security rbac xacml abac

我们有一个中等规模的商业应用程序,我们大量使用Spring Security角色和权限(RBAC)来为某些实例打开和关闭角色,以及在@PreAuthorize标记内隐藏在SpEL中的规则。

我认为我们实际实施了什么(不知道它是ABAC)。 XACML看起来非常复杂和臃肿,所以我不热衷于这里的答案:

How to change Spring Security roles by context?

有人在没有XACML的情况下完成了轻量级ABAC实施吗?我希望能够让我们分离关注点,因为域对象只需要@PreAuthorize(WRITE)等,我们的授权策略就会与它分离。

从我读过的内容来看,ABAC的基本原理非常简单。你有一个Action(非常像Permission)和一个机制来解决当前的Principal是否拥有给定Subject的权限。

我知道AccessDecisionVoter大致是正确的界面,但我不认为它是用于对权限进行投票。然而,实施我们的授权政策与这样的事件似乎非常有吸引力。

抱歉这个漫无边际的问题!基本上我在ABAC很有意思,但我想避免家酿,但担心当我们需要赛斯纳时,XACML是一架大型喷气式飞机。

3 个答案:

答案 0 :(得分:11)

您的目标似乎有两件事:

  1. 外部化授权,您希望将访问控制策略从代码中移出(或者至少在代码中的中心位置,而不是分散在Spring代码中)
  2. 基于属性的授权,您希望使用比角色和权限更丰富的属性
  3. 我不太确定(2)因为你说你想做什么,“如果现任校长有这个许可,行动和解决机制”,在我的书中仍然是RBAC。您是否有其他条件需要基于哪些访问授权决策?用户的位置,一天中的时间,数据库中某些数据的值,被执行的资源的属性等等。如果是这样,我们就会误入ABAC世界。无论哪种方式,我都会说RBAC是ABAC的一个子集,因为角色只是一个属性。

    现在,对于(1),一般模式是首先集中授权引擎并使用Spring注释来调用此authz。用于访问决策的引擎。你有两个选择:

    • 嵌入式authz。引擎:库实现引擎,并由代码作为Java函数调用。可以是XACML引擎,也可以是您自己的RBAC / ABAC实现
    • 作为网络服务:基于网络的(微)服务应答访问控制决策问题。可以是XACML引擎,也可以是您自己的RBAC / ABAC实现

    为了让基于Spring的代码调用此authz。引擎,一种方法是编写自己的Spring Security选民。我发现更容易的另一种方法是编写自己的基于Spring表达式的表达式,然后可以使用现有的@PreAuthorize,@ PostAuthorize,@ PreFilter和@PostFiler,sec:authorize标签甚至来自intercept-url调用它们。条件。

    这是我在Spring Security XACML PEP SDK工作时使用的内容。即使您决定不将XACML用于访问决策策略或请求/响应通信,该方法也应该同样有效。

答案 1 :(得分:1)

这里可以找到一个没有XACML的漂亮方法。这基本上就是你想要的。 ABAC上的轻量级方法,无需实现XACML。 https://dzone.com/articles/simple-attribute-based-access-control-with-spring

答案 2 :(得分:0)

我知道这个问题还很老,但是最近我们需要类似的ABAC权限实现。最初,我试图找到可以满足我们需求的东西,但是一切似乎都过头了,很难使用。

所以我想出了一个非常简单的库,叫做 jaclp ,可以在GitHub上找到。它支持经典的 RBAC 方法和更复杂的 ABAC ,例如,可以在充当资源的JPA实体上使用。集成和设置应该非常简单。

缺点之一是,目前,权限的定义仅以编程方式进行。我计划介绍将从中加载权限规则的配置文件。同样, jaclp 库现在仅支持代码中定义的静态权限规则,这意味着您不能动态地(例如,从数据库中)加载权限规则。

示例用法:

// Applying permissions on REST endpoints

@GetMapping("groups/{id}")
@PreAuthorize("hasPermission(#id, 'group', 'viewDetail')")
public GroupDetailDTO getGroupDetail(@PathVariable long id) {
    return this.groupService.getGroupDetail(id);
}

// Defining role with both RBAC and ABAC approach

Role userRole = RoleBuilder.create("user")
        .addAllowedRule("group",
                (UserDetails user, GroupEntity group) -> group.isPublic(), 
                "viewDetail")
        .addAllowedRule("group", "viewAll")
        .build();