使用Spring Security ACL授予对现有对象标识的权限

时间:2013-10-07 18:08:47

标签: spring spring-security spring-security-acl

我正在使用Spring Security ACL实现,并且想知道为现有对象标识授予角色/用户(安全标识 - SID)新权限的最佳方法是什么。

例如,假设我有以下内容(我主要省略主键和其他一些列,只是通过字符串值引用以便于阅读):

  • ACL_SID:ROLE_TEST
  • ACL_CLASS:test_class
  • ACL_OBJECT_IDENTITY:
    • id:1
    • object_id_class:test_class
    • object_id_identity:someObjectInstanceId
  • ACL_ENTRY:
    • acl_object_identity:1
    • sid:ROLE_TEST
    • mask:CREATE(这将是db中的整数)

现在,我想为WRITE类的所有未来和现有对象的角色ROLE_TEST授予权限test_class。对于将来创建的对象,我只需检查角色的权限并授予它们。但是现有的物体呢?

Spring是否提供了轻松的功能,或者我必须编写自己的自定义代码来执行以下操作(这不会太糟糕但是如果Spring已经提供了这个,我宁愿不自己做):< / p>

  1. 检索具有我想授予新权限的角色/用户的SID的所有ACL条目,并引用具有相应object_id_class的对象标识。
  2. 对于每个结果,创建一个新的ACL条目,该条目与结果相同,但掩码除外,这将反映新的权限。

1 个答案:

答案 0 :(得分:2)

由于我找不到任何内置的Spring支持,我最终得到了以下自定义代码。不是最有效的,但它做我需要做的事情。

如果有人知道更好的解决方案或有改进以下代码的建议,请告诉我们。

自定义JDBC ACL服务,用于按类型(acl_class)检索所有现有对象标识:

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.security.acls.domain.GrantedAuthoritySid;
import org.springframework.security.acls.domain.ObjectIdentityImpl;
import org.springframework.security.acls.domain.PrincipalSid;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.Sid;

import javax.sql.DataSource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class CustomJdbcAclService {

    private final JdbcTemplate jdbcTemplate;

    private final static String SELECT_EXISTING_BY_CLASS_AND_SID =
            "SELECT DISTINCT " +
            "acl_object_identity.object_id_identity " +
            "FROM acl_object_identity " +
            "LEFT JOIN acl_entry on acl_entry.acl_object_identity = acl_object_identity.id " +
            "LEFT JOIN acl_class on acl_class.id = acl_object_identity.object_id_class " +
            "LEFT JOIN acl_sid on acl_entry.sid = acl_sid.id " +
            "WHERE acl_class.class = ? && acl_sid.sid = ? && acl_entry.granting = 1";

    public CustomJdbcAclService(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    public List<ObjectIdentity> getExistingObjectIdentities(String type, Sid sid) {
        String sidName = getSidName(sid);

        List<Map<String, Object>> results = jdbcTemplate.queryForList(SELECT_EXISTING_BY_CLASS_AND_SID, type, sidName);
        List<ObjectIdentity> oids = new ArrayList<>();

        for (Map<String, Object> result : results) {
            oids.add(new ObjectIdentityImpl(type, (Serializable) result.get("object_id_identity")));
        }

        return oids;
    }

    private String getSidName(Sid sid) {
        String sidName;

        if (sid instanceof PrincipalSid) {
            sidName = ((PrincipalSid) sid).getPrincipal();
        } else if (sid instanceof GrantedAuthoritySid) {
            sidName = ((GrantedAuthoritySid) sid).getGrantedAuthority();
        } else {
            throw new IllegalArgumentException("Unsupported implementation of Sid");
        }
        return sidName;
    }

}

我从另一个ACL服务中调用上述内容:

public class MyAclService {

public void grantPermissionsToExisting(String type, Sid securityIdentity, Permission... permissions) {
        List<ObjectIdentity> existingOids = customJdbcAclService.getExistingObjectIdentities(type, securityIdentity);
        for (ObjectIdentity oid : existingOids) {
            // grantPermissions() gets the ACL of the object identity and inserts the new ACEs
            grantPermissions(oid, securityIdentity, permissions);
        }
    }

}