21

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

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

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

有没有人在没有XACML的情况下完成了轻量级ABAC实现?我希望这将使我们像域对象那样分离关注点,并且我们的授权策略将与之分离。@PreAuthorize(WRITE)

从我所读到的ABAC的基本原理非常简单。如果当前 Principal 对给定的 Subject 具有该权限,则您有一个 Action(非常类似于 Permission)和一个解决机制。

我知道AccessDecisionVoter哪个是大致正确的界面,但我不认为它是为了对权限进行投票。然而,使用类似的实例来实施我们的授权策略似乎非常有吸引力。

对不起,漫无边际的问题!基本上我对ABAC很感兴趣,但想避免自制啤酒,但担心当我们需要塞斯纳时XACML是大型喷气式飞机。

4

3 回答 3

14

您的目标似乎有两件事:

  1. 外部化授权,您希望将访问控制策略移出代码(或至少移入代码的中心位置,而不是分散在 Spring 代码中)
  2. 基于属性的授权,您希望使用比角色和权限更丰富的属性

我不太确定(2),因为在我的书中,您所说的“如果当前委托人拥有该权限,则采取的行动和解决机制”仍然是 RBAC。您是否还有其他条件需要作为访问授权决策的依据?用户的位置、一天中的时间、数据库中某些数据的值、正在操作的资源的属性等?如果是这样,我们就会误入 ABAC 世界。无论哪种方式,我都会说 RBAC 是 ABAC 的一个子集,因为角色只是一个属性。

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

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

为了让基于 Spring 的代码调用这个 authz。引擎,一种方法是编写自己的 Spring Security 投票器。我发现更容易的另一种方法是编写您自己的基于 Spring 表达式语言的表达式,然后您可以使用现有的 @PreAuthorize、@PostAuthorize、@PreFilter 和 @PostFiler、sec:authorize 标记甚至从拦截 url 调用条件。

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

于 2015-08-15T05:26:11.420 回答
4

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

于 2018-04-24T14:23:03.447 回答
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();
于 2020-07-15T08:22:59.550 回答