如何在 Spring Security 3.1 中使用 acl_entry 表中的 mask 字段?

发布于 2024-12-29 11:42:04 字数 1903 浏览 4 评论 0 原文

我使用 Spring Security 3.1 ACL 实现。因此,根据教程,我创建了一个包含下表的 acl 数据库:

CREATE TABLE IF NOT EXISTS `acl_class` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `class` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_2` (`class`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `acl_entry` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `acl_object_identity` bigint(20) NOT NULL,
  `ace_order` int(11) NOT NULL,
  `sid` bigint(20) NOT NULL,
  `mask` int(11) NOT NULL,
  `granting` tinyint(1) NOT NULL,
  `audit_success` tinyint(1) NOT NULL,
  `audit_failure` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_4` (`acl_object_identity`,`ace_order`),
  KEY `foreign_fk_5` (`sid`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `acl_object_identity` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `object_id_class` bigint(20) NOT NULL,
  `object_id_identity` bigint(20) NOT NULL,
  `parent_object` bigint(20) DEFAULT NULL,
  `owner_sid` bigint(20) DEFAULT NULL,
  `entries_inheriting` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_3` (`object_id_class`,`object_id_identity`),
  KEY `foreign_fk_1` (`parent_object`),
  KEY `foreign_fk_3` (`owner_sid`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `acl_sid` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `principal` tinyint(1) NOT NULL,
  `sid` varchar(100) NOT NULL,
  `password` varchar(255) NOT NULL,
  `salt` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

这与以下注释配合使用效果很好:

@PreAuthorize("hasPermission(#element, 'WRITE')")
@PostAuthorize("hasPermission(returnObject, 'READ')")

“读取”和“写入”权限在表 acl_entry 中设置为字段掩码。据我了解,1表示“读取”,2表示“写入”,4表示“创建”,8表示“删除”,16表示“管理”,因为它似乎是一种按位身份验证方法。

  1. 问:我对权利授予的理解是否正确?
  2. 问题:如何指定“读/写”等组合权限?我可以“设置”位 0 (即 int 1)和 1 (即 int 2)以便得到掩码值 1+2=3 吗?

现在我必须为“读”和“写”权限创建单个条目,这不太方便。

I use the Spring Security 3.1 ACL implementation. So based on a tutorial i have created a acl databse with the following tables:

CREATE TABLE IF NOT EXISTS `acl_class` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `class` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_2` (`class`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `acl_entry` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `acl_object_identity` bigint(20) NOT NULL,
  `ace_order` int(11) NOT NULL,
  `sid` bigint(20) NOT NULL,
  `mask` int(11) NOT NULL,
  `granting` tinyint(1) NOT NULL,
  `audit_success` tinyint(1) NOT NULL,
  `audit_failure` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_4` (`acl_object_identity`,`ace_order`),
  KEY `foreign_fk_5` (`sid`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `acl_object_identity` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `object_id_class` bigint(20) NOT NULL,
  `object_id_identity` bigint(20) NOT NULL,
  `parent_object` bigint(20) DEFAULT NULL,
  `owner_sid` bigint(20) DEFAULT NULL,
  `entries_inheriting` tinyint(1) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `unique_uk_3` (`object_id_class`,`object_id_identity`),
  KEY `foreign_fk_1` (`parent_object`),
  KEY `foreign_fk_3` (`owner_sid`)
) ENGINE=InnoDB;

CREATE TABLE IF NOT EXISTS `acl_sid` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `principal` tinyint(1) NOT NULL,
  `sid` varchar(100) NOT NULL,
  `password` varchar(255) NOT NULL,
  `salt` varchar(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB;

This works fine with Anntotations like:

@PreAuthorize("hasPermission(#element, 'WRITE')")
@PostAuthorize("hasPermission(returnObject, 'READ')")

The rights "Read" and "Write" are set in the table acl_entry to the field mask. As i understood 1 means "READ", 2 means "Write", 4 means "Create", 8 means "Delete" and 16 means "Administer", because it seems to be a bitwise authentication method.

  1. Question: Do i have correctly understood the granting of rights?
  2. Question: How do i specify combined rights like "Read/Write"? Can i "set" the bit 0 (which is int 1) and 1 (which is int 2) so i get the mask value 1+2=3?

Now i have to create single entries for the "READ" and "Write" permission, that's not pretty handy.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

层林尽染 2025-01-05 11:42:04

根据 PacktPub 的 Spring Security 3.1

不幸的是,< code>AclImpl 直接比较 [@PostFilter] 注释中 SpEL 表达式中指定的权限与数据库中 ACE 上存储的权限,不使用按位逻辑< /强>。 Spring Security 社区正在争论这是无意的还是有意为之。 。 。

该书中的示例尝试完全按照您所描述的方式进行操作 - 它指定一个具有3角色的用户进行读/写,但该用户被拒绝访问权限掩码为1的对象,用于读取

解决方案是编写您自己的自定义权限评估器。

MyPermissionEvaluator.java

public class MyPermissionEvaluator implements PermissionEvaluator {

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object requiredPermissions) {
        //some way to access your user's assigned permission mask
        int permissionMask = MyUserDetails.getMask();

        //the requiredPermissions object must be cast as a String, and then
        //converted to an integer, even though it is an integer in the ACL table
        int permissionsRequired = Integer.valueOf(requiredPermissions.toString());

        //a simple bitwise OR will identify whether the user has the required permissions
        return ((permissionMask | permissionsRequired) == permissionMask);
    }

    . . .

}

要实际使用此自定义权限评估器,请编辑您的 security.xml 文件:

<security:global-method-security pre-post-annotations="enabled">
    <security:expression-handler ref="expressionHandler"/>
</security:global-method-security>

<bean id="espressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <property name="permissionEvaluator" ref="permissionEvaluator"/>
</bean>

<bean id="permissionEvaluator" class="my.project.package.MyPermissionEvaluator"/>

最后,每当方法或类需要特定权限级别时:

@PreAuthorize("hasPermission(#this, '4')")
public void mySecuredMethod() { //some secured method
}

现在您可以设置将 ACL 表中的权限掩码更改为与您的组织需求相对应的内容(按位),并以您标识每个用户权限的任何方式执行相同的操作。例如,

user    site_admin_bit    database_admin_bit    edit_data_bit    write_data_bit    read_data_bit
nancy        0                   1                   1                 0                1

Nancy 的权限掩码为 13(可能的 31),存储在您的用户详细信息实现中。如果她尝试访问权限要求为 edit_data 的对象,系统将根据掩码要求 4 检查她的权限,并进行按位或计算 (permissionMask | requestsRequired ==permissionMask) 将计算为 true

据我估计,这是实现特定于组织的按位权限掩码的最简单方法(可以使用 32 位,我认为这应该足够了)。根据参考书,Spring 注解中使用的 hasPermission SpEL 表达式将用户的权限作为一个完整的单元进行评估;如果用户的读/写权限设置为 3,但注释仅针对 (1) 进行评估,则用户将拒绝访问。

According to Spring Security 3.1 by PacktPub:

Unfortunately, the actual implementation of AclImpl directly compares the permission specified in our SpEL expression in our [@PostFilter] annotation, and the permission stored on the ACE in the database, without using bitwise logic. The Spring Security community is in debate about whether this is unintentional or working as intended. . .

The example in that book tries to do exactly what you're describing -- it specifies a user with a role of 3 for read/write, but the user is denied access to an object with a permission mask of 1 for read.

The solution is to write your own custom permission evaluator.

MyPermissionEvaluator.java:

public class MyPermissionEvaluator implements PermissionEvaluator {

    @Override
    public boolean hasPermission(Authentication authentication, Object targetDomainObject, Object requiredPermissions) {
        //some way to access your user's assigned permission mask
        int permissionMask = MyUserDetails.getMask();

        //the requiredPermissions object must be cast as a String, and then
        //converted to an integer, even though it is an integer in the ACL table
        int permissionsRequired = Integer.valueOf(requiredPermissions.toString());

        //a simple bitwise OR will identify whether the user has the required permissions
        return ((permissionMask | permissionsRequired) == permissionMask);
    }

    . . .

}

To actually use this custom permission evaluator, edit your security.xml file:

<security:global-method-security pre-post-annotations="enabled">
    <security:expression-handler ref="expressionHandler"/>
</security:global-method-security>

<bean id="espressionHandler" class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <property name="permissionEvaluator" ref="permissionEvaluator"/>
</bean>

<bean id="permissionEvaluator" class="my.project.package.MyPermissionEvaluator"/>

Finally, whenever a method or class requires a certain permission level:

@PreAuthorize("hasPermission(#this, '4')")
public void mySecuredMethod() { //some secured method
}

Now you can set the permission mask in the ACL table to whatever corresponds to your organizational needs (bitwise), and do the same in whatever way you identify each individual user's permissions. For example,

user    site_admin_bit    database_admin_bit    edit_data_bit    write_data_bit    read_data_bit
nancy        0                   1                   1                 0                1

Nancy thus has a permission mask of 13 (out of a possible 31) as stored in your user details implementation. If she tries to access an object with a permission requirement of edit_data, her permissions would be checked against a mask requirement of 4, and a bitwise OR evaluation (permissionMask | permissionsRequired == permissionMask) would evaluate to true.

This is, in my estimation, the easiest way to implement an organization-specific bitwise permissions mask (with 32 bits to play with, which should be enough, I should think). According to the referenced book, the hasPermission SpEL expression used in Spring annotations evaluates the user's permissions as a complete unit; if the user has a permission set at 3 for read/write, but the annotation only evaluates against read (1), the user will be denied access.

掀纱窥君容 2025-01-05 11:42:04

为了实现逐位权限评估,您可以用自己的 PermissionEvaluator 覆盖 DefaultPermissionGrantingStrategy,而不是实现 PermissionEvaluator(这可能相当困难)。

这可能是您的 Spring ACL 配置

1) 您的 ACL 服务

<bean class="org.springframework.security.acls.jdbc.JdbcMutableAclService" id="aclService">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="lookupStrategy"/>
<constructor-arg ref="aclCache"/>
</bean>

2) 您的查找策略(dataSource、aclCache 和 aclAuthorizationStrategy 是默认策略)

<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="aclCache"/>
<constructor-arg ref="aclAuthorizationStrategy"/>
<constructor-arg ref="permissionGrantingStrategy"/>
</bean>

3) 这里是有趣的部分,PermissionGrantingStrategy (http://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/acls/model/PermissionGrantingStrategy.html

<bean id="permissionGrantingStrategy" class="com.example.MyPermissionGrantingStrategy"/>

这是您的位置会实现逐位权限逻辑,然后覆盖Spring的默认权限逻辑。

我希望这可以帮助

In order to implement a bit-wise permission evaluation, instead of implementing a PermissionEvaluator, which can be quite difficult, you can override the DefaultPermissionGrantingStrategy with your own one.

This could be your Spring ACL configuration

1) Your ACL Service

<bean class="org.springframework.security.acls.jdbc.JdbcMutableAclService" id="aclService">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="lookupStrategy"/>
<constructor-arg ref="aclCache"/>
</bean>

2) Your lookup strategy (dataSource, aclCache and aclAuthorizationStrategy are the default ones)

<bean id="lookupStrategy" class="org.springframework.security.acls.jdbc.BasicLookupStrategy">
<constructor-arg ref="dataSource"/>
<constructor-arg ref="aclCache"/>
<constructor-arg ref="aclAuthorizationStrategy"/>
<constructor-arg ref="permissionGrantingStrategy"/>
</bean>

3) Here comes the interesting part, the PermissionGrantingStrategy (http://docs.spring.io/spring-security/site/docs/current/apidocs/org/springframework/security/acls/model/PermissionGrantingStrategy.html)

<bean id="permissionGrantingStrategy" class="com.example.MyPermissionGrantingStrategy"/>

Here is where you would implement the bit-wise permission logic, and then override the Spring's default one.

I hope this can help

假情假意假温柔 2025-01-05 11:42:04

来自 SpringSecurity

上一段提到,ACL系统使用整数位
掩蔽。别担心,您不需要了解位的细节
转向使用 ACL 系统,但足以说明我们有 32
我们可以打开或关闭位。这些位中的每一个都代表一个
权限,默认情况下权限为读(位0)、写
(位 1)、创建(位 2)、删除(位 3)和管理(位 4)。它是
如果您想使用,可以轻松实现您自己的 Permission 实例
其他权限,ACL 框架的其余部分将运行
不知道您的扩展。

@question#1:是的,没错。

@question#2:你可以使用类似的东西:
new BasePermission(BasePermission.WRITE.getMask() | BasePermission.READ.getMask())
获得READWRITE权限。

来自春季文档:

// Prepare the information we'd like in our access control entry (ACE)
ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44));
Sid sid = new PrincipalSid("Samantha");
//Permission p = BasePermission.ADMINISTRATION;
Permission p = new BasePermission(BasePermission.WRITE.getMask() | BasePermission.READ.getMask());    

// Create or update the relevant ACL
MutableAcl acl = null;
try {
  acl = (MutableAcl) aclService.readAclById(oi);
} catch (NotFoundException nfe) {
  acl = aclService.createAcl(oi);
}

// Now grant some permissions via an access control entry (ACE)
acl.insertAce(acl.getEntries().length, p, sid, true);
aclService.updateAcl(acl);

From SpringSecurity

As mentioned in the last paragraph, the ACL system uses integer bit
masking. Don't worry, you need not be aware of the finer points of bit
shifting to use the ACL system, but suffice to say that we have 32
bits we can switch on or off. Each of these bits represents a
permission, and by default the permissions are read (bit 0), write
(bit 1), create (bit 2), delete (bit 3) and administer (bit 4). It's
easy to implement your own Permission instance if you wish to use
other permissions, and the remainder of the ACL framework will operate
without knowledge of your extensions.

@question#1: yes that's right.

@question#2: you could use something like:
new BasePermission(BasePermission.WRITE.getMask() | BasePermission.READ.getMask())
to get a READ and WRITE permission.

From the spring docs:

// Prepare the information we'd like in our access control entry (ACE)
ObjectIdentity oi = new ObjectIdentityImpl(Foo.class, new Long(44));
Sid sid = new PrincipalSid("Samantha");
//Permission p = BasePermission.ADMINISTRATION;
Permission p = new BasePermission(BasePermission.WRITE.getMask() | BasePermission.READ.getMask());    

// Create or update the relevant ACL
MutableAcl acl = null;
try {
  acl = (MutableAcl) aclService.readAclById(oi);
} catch (NotFoundException nfe) {
  acl = aclService.createAcl(oi);
}

// Now grant some permissions via an access control entry (ACE)
acl.insertAce(acl.getEntries().length, p, sid, true);
aclService.updateAcl(acl);
他不在意 2025-01-05 11:42:04

这个答案指出Spring会比较ACE掩码和我们正在检查的权限之间的精确匹配。正如OP所说:

现在我必须为“READ”和“Write”创建单个条目
许可,这不太方便。

-是的。这似乎是默认行为。正如我们从提供的任何数据库模式中看到的 此处,我们可以为给定对象添加多个条目。因此,如果我们想授予 Alice 读取和写入访问权限,我们将添加一个读取条目,顺序可能为 1,然后添加一个写入条目,顺序为 2 或其他。

尽管默认行为似乎如上所示,但文档中提到的“按位”可能会让新手感到困惑。然而,我想,对于一个已经存在这么久并被这么多人依赖的框架的向后兼容性,改变默认行为可能已经太晚了。 Spring 开发人员似乎很清楚这个难题,因此他们提供了一种足够简单的方法来克服它。正如这个答案指出的,关键是提供自定义的PermissionGrantingStrategy。链接的答案显示了如何通过 XML 在类中进行挂钩。不过,我对基于代码的配置更满意,因此我遵循了 此链接,它解释了如何在代码中设置 Spring ACL。

现在,您所要做的与该链接中描述的不同,就是替换此 Bean 定义:

@Bean
public PermissionGrantingStrategy permissionGrantingStrategy() {
    return new DefaultPermissionGrantingStrategy(
      new ConsoleAuditLogger());
}

并返回您自己制定的权限授予策略。不过别担心!您不必完全从头开始编写自己的类。然后,您的自定义权限授予策略只需创建 DefaultPermissionGrantingStrategy 类的子类型并仅重写 isGranted 方法。默认实现确实只是进行完全匹配:

protected boolean isGranted(AccessControlEntry ace, Permission p) {
    return ace.getPermission().getMask() == p.getMask();
}

但根据该方法文档中的这段代码,作者似乎很清楚需要进行覆盖:

默认情况下,我们会比较权限掩码是否完全匹配。
该策略的子类可以覆盖该行为并实现
更复杂的比较,例如 ACE 的按位比较
授予访问权限。

该文档甚至进一步实际为您提供了进行覆盖的代码。我还没有测试过这个,但我相信这只是:

protected boolean isGranted(AccessControlEntry ace, Permission p) {
        if (ace.isGranting() && p.getMask() != 0) {
            return (ace.getPermission().getMask() & p.getMask()) != 0;
         } else {
            return ace.getPermission().getMask() == p.getMask();
         }
}

你应该使用按位 ACL 吗?

在覆盖 Spring ACL 默认使用按位存储之前,您应该首先问自己是否值得付出额外的努力以及因偏离 OOTB 行为而产生错误的风险。

而且,您还应该意识到,您将失去非按位 Spring ACL 中可用的一些行为:即删除 ACE 的能力。我将用一个例子来演示。假设有一个名为 CCompany 对象和一个名为 DDepartment 对象,该对象嵌套在 C 下 在 Spring ACL 层次结构中。假设DC继承了它的权限。

现在假设 Alice 拥有整个公司 C 的 READ 访问权限。由此,她继承了对 C 下所有部门(包括 D)的 READ 访问权限。有一天,Bob 决定只授予 Alice 对部门 D 的 WRITE 访问权限,而不授予任何其他部门。通过按位逻辑,D 会添加什么 ACE?由于单个 ACE 必须包括编码到各个位中的所有读、写等权限,因此读位必须为 0 或 1。两者都可能存在问题:

  1. 假设新 ACE 上的读位为 0。假设 Alice 现在被拒绝对 D 进行读取访问,因此我们必须假设 0 位并不意味着“被拒绝”,而是较弱的含义“未授予”。这意味着 ACL 逻辑仍将查找父对象来授予权限。这意味着我们失去了拒绝覆盖在层次结构中更高级别授予的权限的能力。
  2. 另一方面,我们可以实现更复杂的逻辑,检测 Alice 通过父对象 C 具有 READ 访问权限,因此将新 ACE 上的 READ 位设置为 1。但是,如果我们删除 Alice 对 C 的 READ 访问权限,会发生什么?没有办法知道对 D 的 READ 访问是否也应该被删除,除非我们将该信息存储在某个地方,而这样做会破坏按位 ACL 的全部意义,即压缩存储。

解决此问题的一种方法是为每个权限使用两位位,而不是 1。例如,您可以解释如下:00 表示未授予或拒绝 - 向父母查找值,01 表示拒绝,10 表示同意。在这种情况下,11 是免费的,但您稍后可能会将其用于其他用途,例如。但是,使用 2 位执行此操作会更复杂,因为 OOTB 权限只有 1 位,因此您必须编写自己的权限。尽管付出了所有这些努力,最终您只能获得一半的存储压缩。

This answer pointed out that Spring compares for an exact match between the ACE mask and the permission we're checking. As the OP says:

Now i have to create single entries for the "READ" and "Write"
permission, that's not pretty handy.

-Yes. This seems like the default behaviour. As we can see from any of the DB schemas presented here, we are allowed to add multiple entries for a given object. So if we want to grant Alice read and write access, we'd add an entry for read, maybe with order 1, and then an entry for write, with order 2 or something.

Although the default behaviour seems to be as above, the mention of "bitwise" in the documentation is probably confusing newcomers. However, I'd imagine that for backwards compatibility of a framework that's been around for so long and relied upon by so many, it's probably too late to change the default behaviour. The Spring developers seem to be well aware of this conundrum, and so they have provided a simple enough way to overcome it. As this answer points out, the key is to provide a custom PermissionGrantingStrategy. The linked answer shows how to do hook in the class via XML. I am more comfortable with code based configuration though, so I followed this link which explains how to do set up Spring ACL in code.

Now, all you have to do that's different to what's described in that link, is to replace this Bean definition:

@Bean
public PermissionGrantingStrategy permissionGrantingStrategy() {
    return new DefaultPermissionGrantingStrategy(
      new ConsoleAuditLogger());
}

And instead return a permission granting strategy of your own making. Don't worry though! You don't have to write your own class completely from scratch. Your custom permission granting strategy can then just subtype the class DefaultPermissionGrantingStrategy and override only the method isGranted. The default implementation indeed just does an exact match:

protected boolean isGranted(AccessControlEntry ace, Permission p) {
    return ace.getPermission().getMask() == p.getMask();
}

But the author seems well aware of the need for an override, based on this snippet from the method's doc:

By default, we compare the Permission masks for exact match.
Subclasses of this strategy can override this behavior and implement
more sophisticated comparisons, e.g. a bitwise comparison for ACEs
that grant access.

The documentation goes even further to actually give you the code to do the override. I haven't tested this, but I believe it's just:

protected boolean isGranted(AccessControlEntry ace, Permission p) {
        if (ace.isGranting() && p.getMask() != 0) {
            return (ace.getPermission().getMask() & p.getMask()) != 0;
         } else {
            return ace.getPermission().getMask() == p.getMask();
         }
}

Should you Use Bitwise ACL?

Before overriding Spring ACL's default to use bitwise storage, you should first ask yourself is it worth the extra effort and the risk of bugs by deviating from OOTB behaviour.

But also, you should be aware that you will lose some behaviour that is available in non-bitwise Spring ACL: namely the ability to delete ACEs. I'll demonstrate with an example. Suppose there is a Company object called C and a Department object called D which is nested underneath C in the Spring ACL hierarchy. And suppose D inherits its permissions from C.

Now suppose Alice has READ access to the entire company C. From this, she inherits READ access to all departments underneath C, including D. One day, Bob decides he wants to grant Alice WRITE access to the department D only, but not any other departments. With bitwise logic, what ACE gets added for D? Since the single ACE must include all permissions READ, WRITE etc. encoded into the various bits, the READ bit must be either 0 or 1. Both are potentially problematic:

  1. Suppose the READ bit on the new ACE is 0. It would be crazy to assume Alice is now denied READ access to D, so we'd have to assume that a 0 bit doesn't mean "denied" but the weaker meaning "not granted". Meaning the ACL logic will still look to parent objects to grant the permission. This means that we lose the ability to DENY-override permissions that were granted at a higher level in the hierarchy.
  2. On the other hand, we could implement a more complex logic which detects that Alice has READ access via the parent object C and so sets the READ bit to 1 on the new ACE. But then what happens if we remove Alice's READ access to C? There is no way to know that the READ access to D should also be removed, unless we store that info somewhere, and doing so would defeat the whole point of bitwise ACLs which is to compress storage.

One way around this would be to use two bits for every permission, instead of 1. For example, you could interpret as follows: 00 means not granted or denied - look to parents for a value, 01 means denied, 10 means granted. 11 would be free in that case, but you might use it for something else later, for example. However, doing it with 2 bits would be more complex because the OOTB permissions are only 1 bit, so you'd have to write your own. And for all that effort, you'd only get half the storage compression at the end of it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文