回想一下,我们非常简单的场景是只允许 [email protected] 访问生日聚会事件,并确保没有其他事件可以访问。您可能会发现参考数据库模式图的几页以了解我们要插入哪些数据以及为什么插入会很有帮助。
我们已经在示例应用程序中包含了一个名为 data.sql 的文件。本节中解释的所有 SQL 都来自该文件——您可以根据我们提供的示例 SQL 随意试验和添加更多测试用例——事实上,我们鼓励您使用示例数据进行试验!
让我们看一下创建简单 ACL 条目的以下步骤:
- First, we'll need to populate the ACL_CLASS table with any or all of the domain object classes, which may have ACL rules—in the case of our example, this is simply our Event class:
对于 ACL_CLASS 表,我们选择使用 10 到 19 之间的主键,20 到 29 用于 ACL_SID 表,依此类推。这将有助于更容易理解哪些数据与哪个表相关联。请注意,我们的 Event 表以 100 的主键开始。这些便利是出于示例目的,不建议用于生产目的。
- Next, the ACL_SID table is seeded with SIDs that will be associated with the ACEs. Remember that SIDs can either be roles or users—we'll populate the roles and [email protected] here.
- While the SID object for roles is straightforward, the SID object for a user is not quite as clear-cut. For our purposes, the username is used for the SID. To learn more about how the SIDs are resolved for roles and users, refer to o.s.s.acls.domain.SidRetrievalStrategyImpl. If the defaults do not meet your needs, a custom o.s.s.acls.model.SidRetrievalStrategy default can be injected into AclPermissionCacheOptimizer and AclPermissionEvaluator. We will not need this sort of customization for our example, but it is good to know that it is available if necessary:
事情开始变得复杂的表是 ACL_OBJECT_IDENTITY 表,用于声明各个域对象实例、它们的父级(如果有)和拥有 SID。例如,此表表示我们正在保护的 Event 对象。我们将插入具有以下属性的行:
- Domain object of type Event that is a foreign key, 10, to our ACL_CLASS table via the OBJECT_ID_CLASS column.
- Domain object primary key of 100 (the OBJECT_ID_IDENTITY column). This is a foreign key (although not enforced with a database constraint) to our Event object.
- Owner SID of [email protected], which is a foreign key, 20, to ACL_SID via the OWNER_SID column.
表示我们的事件 ID 为 100(生日事件)、101 和 102 的 SQL 如下:
请记住,拥有的 SID 也可以代表一个角色——就 ACL 系统而言,这两种类型的规则功能相同。
最后,我们将添加一个与此对象实例相关的 ACE,它声明允许 [email protected] 对生日事件进行读取访问:
这里的MASK 列代表一个位掩码,用于授予分配给相关对象上所述SID 的权限。我们将在本章后面解释这方面的细节——不幸的是,它并不像听起来那么有用。
现在,我们可以启动应用程序并运行我们的示例场景。尝试使用 [email protected]/user2 登录并访问 所有事件 页面。您将看到仅列出生日事件。当使用 [email protected]/admin1 登录并查看 所有事件 页面时,不会显示任何事件。但是,如果我们直接导航到一个事件,它就不会受到保护。你能根据你在本章中学到的知识弄清楚如何保护对事件的直接访问吗?
如果您还没有弄清楚,您可以通过对 CalendarService 进行以下更新来确保直接访问事件,如下所示:
我们现在有了基于 ACL 的安全性的基本工作设置(尽管是一个非常简单的场景)。让我们继续对我们在本演练中看到的概念进行更多解释,然后回顾典型 Spring ACL 实现中的几个注意事项,您应该在使用它之前考虑这些注意事项。
Your code should look like
chapter12.01-calendar.
值得注意的是,我们在创建事件时并没有创建新的 ACL 条目。因此,在当前状态下,如果您创建一个事件,您将收到类似于以下的错误:
Spring Security 应用程序执行期间出现异常!找不到对象身份 org.springframework.security.acls.domain.ObjectIdentityImpl [类型:com.packtpub.springsecurity.domain.Event;标识符:103].