我设计的系统对用户管理/权限有很多要求,因此我决定使用Spring Security ACL来管理域对象级别的权限。
尽管使用ACL来维护用户和实体之间的关系迫使我们依赖它来在UI上显示数据。
Spring Security提供的PostFilter解决方案可以很好地过滤用户可以/无法看到的对象,但是当我们处理具有数百/数千个条目的实体时,它会遇到很大的性能问题,因为我们需要从数据库中加载所有内容,然后丢弃用户不允许的对象"请参阅"。
此问题在此处进行了描述 - SEC-2409 - 但在此功能可用之前需要一些时间。因此,我试图找到一种解决方法来使用Spring Security ACL,但避免了性能问题。
我考虑过实现一些代码来检索用户可以访问的对象(在身份验证过程之后)并保持该信息可用于每个请求,以允许开发人员使用该信息来执行查询而不是依赖在PostFilter上。
为了实现这一点,我试图找到一种方法来检索给定主体/授权机构的权限列表,但是我无法找到一种方法来实现AclService实现。
示例:aclService.getObjectIdentityList(<sid>,<acl_class>)
注意:该方法应使用继承结构并包含从父条目继承的所有ObjectIdentities
有任何关于获取数据或其他方法来解决此问题的建议吗?
更新
我已经找到了一种方法来检索用户可以访问的对象列表。
List<ObjectIdentity> childObjects = aclService.findChildren(objectIdentity);
Map<ObjectIdentity, Acl> result = aclService.readAclsById(childObjects, sids);
这种方法对我们有用,因为我们只有一些实体可以通过ACL控制访问,因此我们可以构建用户可以访问的ObjectsIdentities列表。
虽然正在返回的Map正在返回正在传递的ObjectIdentities的所有ACL,然后我需要检查用户是否有权访问正在返回的每个ObjectIdentity。
您是否有简单的方法来完成此操作或简化所有这些逻辑?
答案 0 :(得分:1)
当前处理大型数据集的方法是更新查询以在查询中包含当前登录的用户。例如,您可以使用Spring Security和Spring Data集成来更新查询以引用当前用户:
@Query("select d from MyDomain d where d.owner = #{principal.name}")
显然这不太理想,因为您需要手动管理权限。一旦我们解决了SEC-2409 Spring,就可以自动为你做很多繁重的工作。
答案 1 :(得分:0)
我遇到了这个问题,需要一个解决方案来解决SEC-2409的不足。看看JdbcAclService.findChildren()引导我进入这个
private final String FIND_OBJECTS_WITH_ACCESS = ""+
"SELECT " +
" obj.object_id_identity AS obj_id, " +
" class.class AS class " +
"FROM " +
" acl_object_identity obj, " +
" acl_class class, " +
" acl_entry entry " +
"WHERE " +
" obj.object_id_class = class.id " +
" and entry.granting = true " +
" and entry.acl_object_identity = obj.id " +
" and entry.sid = (SELECT id FROM acl_sid WHERE sid = ?) " +
" and obj.object_id_class = (SELECT id FROM acl_class WHERE acl_class.class = ?) " +
"GROUP BY " +
" obj.object_id_identity, " +
" class.class ";
public List<ObjectIdentity> getObjectsWithAccess(Class clazz, String sid) {
Object[] args = { sid, clazz.getName() };
List<ObjectIdentity> objects = _jdbcTemplate.query(FIND_OBJECTS_WITH_ACCESS, args, getRowMapper());
return objects.size() == 0 ? null : objects;
}
private RowMapper<ObjectIdentity> getRowMapper() {
return (rs, rowNum) -> {
String javaType = rs.getString("class");
Long identifier = rs.getLong("obj_id");
return new ObjectIdentityImpl(javaType, identifier);
};
}