虽然角色成员资格检查在某种程度上是一种反模式(最好对权限或活动进行编码),但它们通常用于服务级别访问控制(Web 请求和方法调用),但根本不是适合在多租户设置中保护实际域对象,例如防止用户访问具有相同角色的其他用户的资源。
您检查经过身份验证的登录是否与特定域对象相关联的方法可行,但它很麻烦,会将您的应用程序数据模型与安全数据模型耦合和/或污染,并且正如您所怀疑的那样,这不是最佳实践.
您已经确定了一些选项:
Apache Shiro 提供了支持域对象访问控制的一致且易于使用的 API,但您负责提供后端“领域”,这意味着您可能必须实现您的拥有自己的数据存储和/或 DAO。
Spring Security ACLs 是 Spring 用于保护域对象的访问控制范例。它将安全数据模型与您的应用程序数据模型分离。访问控制列表可以通过添加或查找 ACL 条目轻松地授予或检查对域对象的访问权限,但如果您想有效地找到用户有权访问的所有域对象(例如,呈现那些列表中的对象或撤销对它们的访问)。此外,您有责任维护 ACL,因为:
Spring Security 不提供任何特殊集成来自动创建、更新或删除 ACL,作为 DAO 或存储库操作的一部分。相反,您需要为您的各个域对象编写代码 [...]。值得考虑在您的服务层上使用 AOP 以自动将 ACL 信息与您的服务层操作集成。
——Spring Security 4.0 reference
最后,如果默认 API 与您的应用程序模型不兼容(例如,如果您的域对象没有公共 getId() 或不使用与 @ 兼容的 ID,则您必须自定义 ACL 实现987654326@)
如果您没有与 Spring 或 Shiro 结婚以提供域对象访问控制,那么还有另一种选择:
OACC,一个开源 Java 安全框架(披露:我是维护者和共同作者),它为 enforce 和管理您的授权需求。 OACC 是一个完整的访问控制框架,具有丰富的 API,无需任何 DIY 实现即可实现细粒度授权的编程和动态建模。它的安全模型具有完全实现的 RDBMS 支持的数据存储,API 在幕后为您管理。
OACC 的安全模型是基于权限的:它本质上管理资源 之间的权限。资源既代表受保护的域对象,也代表它们上的参与者(即主体)。它还提供高效的查询方法,通过权限查找资源,无需先加载所有资源,然后过滤掉未经授权的资源。这些方法是对称的,您既可以找到指定资源对其具有特定权限集的资源,也可以找到对指定资源具有特定权限集的资源
将下面授予权限的 OACC 片段与sample code from the Spring Security ACL reference 进行比较:
// get the resource representing the principal that we want to grant permissions to
User accessorUser = Users.findByName("Samantha");
Resource accessorResource = Resources.getInstance(accessorUser.getId());
// get the resource representing the object that we want to grant permissions to
Resource accessedResource = Resources.getInstance(Foos.findById(44).getId());
// Now grant some permissions
Permission permission = ResourcePermissions.getInstance("ADMINISTER");
oacc.grantResourcePermissions(accessorResource,
accessedResource,
permission);
要检查授权,您可以调用
oacc.assertResourcePermissions(accessorResource, accessedResource, permission);
或检查返回值
oacc.hasResourcePermissions(accessorResource, accessedResource, permission);
OACC 的另一个新特性是 create-permissions,它不仅可以控制主体可以创建什么样的资源,还可以准确定义他们在新资源上获得的权限创建它 - 定义一次,权限会自动分配给资源创建者,无需显式 API 调用。
总之,OACC 是专门针对您经过身份验证的细粒度授权的用例而开发的。