利用并实现非常有用的 IBM Lotus Notes/Domino 安全特性 Reader Names 字段。了解该特性对复制、代理和视图的影响,以及如何对使用 Reader Names 字段产生的两种常见问题进行故障检修。
Reader Names 字段(也称为 Reader and Author Access 或 Reader Names)限制了对 IBM Lotus Notes/Domino 数据库中文档的访问。该安全特性为防止有害入侵提供了强力保护,并且能够使指定用户方便地访问其应该查看的文档。换句话说,它是用来授予数据访问权限的智能化、粒度化方法。本文提供了实现 Reader Names 字段的具体过程,并给出了很多技巧,以帮助避免在实现过程中出现的问题。
尽管理解概念和示例不需要具备一定水平的专业知识,但本文适用于 Notes/Domino 应用程序开发人员。
Lotus Notes/Domino 中的安全方法概述
Lotus Notes/Domino 提供了很多保护数据库数据的方法。下面列出了比较常用的方法的简要概述,以便了解 Reader Names 字段的适用场合:
尽管上述每个主题都很有趣,并且都值得关注,但是本文将重点讨论使用 Reader Names 字段来保护数据。
如果使用 Notes 客户机或 Web 浏览器的用户对数据库进行访问,那么假定他已获得上述列表中的第三种访问权。如果没有采取其他任何安全措施(例如 Reader Names 字段),那么从理论上讲该用户可以找到访问任何文档的方法。例如,通过在主视图中不包含数据来隐藏数据(尽管从开发角度看很容易实现)并不能阻止决心找到该数据的人发现它。
基于对 Lotus Notes/Domino 中各种可用的安全措施的多年研究、测试以及使用,我们创建了表 1 来帮助您确定不同场合中最适合的安全措施。
注意:术语 “模糊 (obfuscation)” 用于表示通过在公共视图中不显示数据来隐藏数据,或通过使用 hide-when 公式来隐藏表单上的数据。这并不是真正的安全,但该方法在某些情况下很有用。
安全类型 | 优点/缺点 | 实现方式 |
模糊 |
|
使用表单字段上或导航选项上的 Hide-when 属性。也可以使用 View Properties 框中的 hide-when 属性来隐藏视图。 |
Reader Names 字段 |
|
借助表单上 Reader 类型的字段是实现该安全措施最常用的方法。 |
加密 |
|
对适当的字段启用加密,然后使用密钥或公钥进行加密,只有具有正确 ID 的 Notes 客户机用户才能访问该字段。 |
从表 1 可以看出使用 Reader Names 字段比其他安全形式更具优势。它们不但提供了真正的安全,而且如果具有适当的访问权限(无论是使用 Notes 客户机还是 Web 浏览器),还便于使用。严格地说,可以在视图中查看数据,并且代理能够以编程方式访问数据。最后,该方式易于实现,并且如果将来需要更改安全或业务,也易于修改。
|
实现 Reader Names 字段
若要使用 Reader Names 字段,通常在 Field Properties 框中将字段类型设置为 Readers(参见图 1)。这样即可。使用用户名称、组或角色(本文稍后将进行讨论)填写这些字段后,只有指定用户才能查看基于该表单的文档。
将该字段设置为多值(multi-value)很有好处,这样可以向字段添加多个名称。如果使用该表单保存一个文档,然后查看该字段属性,那么将看到 Field Flags 列出了 SUMMARY READ-ACCESS NAMES(参见图 1)。这表示可以在视图中查看数据 (SUMMARY),而且它是 Reader Names 字段 (READ-ACCESS NAMES)。使用 Reader Names 字段时常见的错误是忘记为该字段设置正确的类型,所以执行文档属性快速检查是个不错的方法,以便确认是否已进行正确设置(参见图 2)。
使用多个 Reader Names 字段
表单上可以有多个 Reader Names 字段。如果有一个以上该字段,那么要确定谁拥有访问权限,从所有 Reader Names 字段获取累积名称。另外,任何能够编辑文档的人都可以添加 Reader 列表(文档属性的最后一个附签),然后该列表被存储为一个名为 $Readers 的字段。如果添加了此类字段,那么在确定文档访问权限时,将该字段视为与其他所有 Reader Names 字段完全一样的字段。
使用 Author 字段
如果创建了 Author 字段,那么应具有 SUMMARY READ-WRITE ACCESS 属性。有趣地是,如果文档上只有 Author 字段,而没有 Reader Names 字段,那么任何人都可以查看该文档。但是,只有拥有数据库的 Author 访问权限的用户(该用户列在 Author 字段中)以及拥有 ACL 中 Editor 访问权限或更高级别访问权限的用户(无论其名称是否在 Author 字段中列出)才能编辑该文档。
但是,如果 Reader Names 字段也存在,那么 Author 字段既可以用作 Reader 列表,也可以用作 Editor 列表。假定某人拥有 ACL 中的 Editor 访问权限,但这两个字段中都没有列出他的名称,那么该用户不能查看文档,而且不能编辑文档,即便他拥有该数据库中所有文档的 Editor 访问权限。如果文档的任何 Reader 字段或 Author 字段(每种类型的字段可以有任意多个)中存在该用户名称,该用户就可以读取并编辑此文档。
也可以使用 LotusScript 以编程方式将此类字段添加到文档,这种情形下,代码如清单 1 所示:
Dim item as NotesItem Set item = doc.ReplaceItemValue ( "RNames", NewValue ) Item.IsReaders = True ‘ Item.IsSummary = True |
在这段代码中,RNames 是 Reader Names 字段的名称,NewValue 是字符串或字符串数组。在 Lotus Notes/Domino 的最新几个版本中,Item.IsSummary = True 是多余的;在早期的版本中,必须保证将新字段保存为 summary 数据。
如果尝试使用 @Formula 语言向文档添加新的 Reader Names 字段,则不会为其指定适当类型。而将其考虑为文本字段。检查文档属性,将看到 SUMMARY,而不是 SUMMARY READ ACCESS。但是如果该字段已经存在且对内容进行了更新,那么 @Formula 语言将保持正确的 Reader 属性。
格式化名称
Reader Names 字段和 Author 字段中的单个名称必须是纯文本格式或规范格式,不能是缩写的格式。例如 CN=Raphael Savir/OU=Boston/O=LSDevelopment 符合要求,Raphael Savir 也符合要求,但是 Raphael Savir/Boston/LSDevelopment 不符合要求。
这可能会造成混淆,因为 Reader Names 或 Author 字段以缩写格式来显示规范数据,以便于阅读。打开文档并读取此类字段中的名称时,将看到 Raphael Savir/Boston/LSDevelopment。但是如果使用文档属性查看底层数据,则会发现这些数据实际上是采用规范格式 CN=Raphael Savir/OU=Boston/O=LSDevelopment 存储的(参见图 3)。这种简化规范名称显示的能力适用于所有 Names 字段,但是不适用于纯文本字段。
如果将纯文本名称填入 Reader Names 或 Author 字段,那么只要服务器和用户拥有相同级别就能够正常运行。例如,假定贵公司与其他公司合并,并且在不同级别的服务器之间复制了数据。假定其中一台服务器称为 Apps/NorthEast/LSDevelopment,另一台服务器称为 HQ/ACME。如果用户尝试访问每个副本中的数据,而且其数据位于 Reader Names字段,而这些字段使用了用户的纯文本名称,那么他只能在 Apps/NorthEast/LSDevelopment 服务器上实现成功操作,因为他仅与该服务器共享级别(其名称中的 /O= 部分)。他可以通过交叉认证来访问另一个服务器 HQ/ACME,但是 Reader Names 和 Author 字段没有授予他访问这些数据的权限。
从这里得到的教训是规范名称最安全。永远不要使用缩写名称,而且仅当您确信不会对数据进行跨公司或跨域复制时,才能使用纯文本名称。
|
使用角色
注意:在本文中讨论业务角色时,通常写作 “角色 (role)”。但是,谈及在每个 Notes 数据库的 ACL 中显示的特性时,将使用 [role] 以示区别。
首次使用 Reader Names 字段时,尝试将需要访问文档的每个单独用户的名称填入该字段中。但是,这不切实际,因为如果用户在公司内部更改业务角色时,必须在很多(也许是成百上千)文档中替换其名称。虽然肯定能够作到准确无误地进行替换,但是除非别无选择,否则您肯定不希望出现这种情形。在很多公司中,经常发生这种情况,因此您需要为此做好准备。
此外,Reader Names 字段可能涉及一大群人。例如,公司中的 30 位主管和经理都需要查看应用程序中的销售数据。为每个文档重复输入这些名称是对空间的浪费,当然,名称愈多,就需要愈频繁地更改名称列表。最后名称列表超出了字段的 32K SUMMARY 数据限制,虽然这是罕见情形,但您肯定有所耳闻。
更可取的做法是尽可能使用组或 [role]。从理论上讲两者都符合要求,不过实际上应尽可能使用 [role]。可通过以下方式来考虑组和 [role] 之间的区别:组是在 Domino Directory 中维护的。存在数以千计的组,如果贵公司与其他公司合并,那么这些组的名称可能发生更改,并且总有可能发生该目录被破坏或其他您一个人无法解决的问题。图 4 展示了将角色指定给用户 Rafael Savir/Boston/LSDevelopment 的 ACL。
另一方面,[role] 是特定于应用程序的。通过在 ACL 中执行一些单击操作,可以将 [role] 应用于一个组或多个组。可以取消一个组的 [role] 并其应用于其他组,必要时,也可以在 ACL 中将 [role] 应用于个别名称。曾出现过目录被破坏的危机情况,但是通过将用户名称临时添加到 ACL 并将相关 [role] 应用于用户名称,就能为用户授予对关键数据的访问权限。如果 Reader Names 字段使用组而不是 [role],则不可能实现上述操作。
若要以这种方式来使用 [role],请考虑需要访问安全文档的组。假定这些组如下所示:
可以用两种方式来解决如何为这些人授予权限的问题。一种方式是为每个组设置一个 [role],另一种方式对这三个组设置一个 [role]。这取决于具体情形,但是由于可以拥有多达 75 个 [role],所以通常可以自由选择如何创建并应用它们。基于多年来使用 [role] 进行应用程序开发的经验,我们编制了以下适用的指导方针。这些并不是绝对准则,但是在每种情形下,应用这些方针都能预防发生问题:
因此,本例子中将创建带有以下 [role] 的 Reader Names 字段:
请注意,由于添加了最后两个 [role],因此所有开发人员和管理员都可以访问这些数据。
|
Reader Names 字段在复制、代理和视图中的作用
现在了解了应该以何种方式设置 [role] 和 Reader Names 字段,下面将花费几分钟时间来考虑一下其他的数据访问方式。具体而言,我们发现在文档上应用 Reader Names 字段后,复制、代理和视图有时可能发生意外行为。本节内容将深入研究各种情形。
复制
如果跨服务器进行数据复制,那么惟一需要注意的事情是在 [Admin] 角色中包含所有服务器(如前所述)。可以通过 LocalDomainServers 组来实现,这样能保证域内的所有服务器可以查看数据库中所有受 Reader 限制的文档。
如果不希望将所有数据复制到所有服务器,那么需要更改此方法。大型销售应用程序就是这样的一个例子,其中每个地理区域仅维护本区域的数据以便简化性能。在这种情况下,可能使用例如 [Servers-APAC]、[Servers-EMEA] 等 [role],并按照地理区域将这些 [role] 应用于文档,然后应用于 ACL 中的个别服务器名称。仍然需要谨慎,以免不小心通过 LocalDomainServers 或其他一些组授予所有服务器访问所有数据的权限,因此制定此类模型之后应小心地进行测试。
更头疼的问题是对本地复制的影响。例如,假定 20,000 名销售代表每人有一台笔记本电脑,并且每晚对自己的数据进行本地复制。如果没有 Reader Names 字段,可能会担心发生复制/保存冲突,不过仅此而已。如果使用 Reader Names 字段,还可能担心本地副本与服务器副本不同步,例如同时在本地副本和服务器副本上编辑文档,而在服务器上的编辑包含从 Reader Names 字段删除该用户名称。
换句话说,如果在进行编辑时两个副本中有一个不能访问所讨论的文档,就无法解决复制冲突问题。结果是服务器、本地副本各自保留自己的编辑,而二者都没有意识到它们已经不同步。对于该问题,没有简单的解决方案,因此在设计整体架构和工作流时应特别注意这一点。
代理
Reader 安全对代理的影响其实很简单。如果代理是由用户触发的,例如通过单击按钮,那么代理在运行时就好像是用户在执行操作。如果该用户拥有文档的访问权限,则代理也拥有文档的访问权限。如果用户没有所讨论文档的访问权限,那么在代理工作时将显示错误(例如,“Entry not found in index” 或 “Unauthorized to attempt that operation”)。
如果是按照计划运行的代理,则代理在运行时就好像是代理的签名人,除非填写了代理的“Run on behalf of”字段,填写该字段后,代理在运行时就好像是用户(参见图 5)。
视图
出于功能性和性能考虑,对用户影响最大的方面可能在于视图。
如果对视图进行了分类,那么用户可能会看到有点古怪的类别,但无法查看该类别内的文档。这对于用户来说是很常见的问题。一种解决方案是使用 Show single category 选项(参见图 6)来创建嵌入视图,并且让用户从其拥有访问权限的类别列表中选择要显示的类别。这样用户不会看到其他类别,所以不会出现空视图。Web 浏览器可以不着痕迹地实现该功能,并且该功能也可以用于 Notes 客户机。另一种解决方案是重新考虑划分类别,以便用户不会看到空类别。
与其他方式相比,Reader Names 字段会使视图执行速度慢很多,因为服务器必须检查每个文档以确保其可以被查看。必须对每个用户执行该操作,因此如果有很多并发用户以及很多带有 Reader Names 字段的文档,那么服务器/应用程序的速度可能显著减慢。当很多用户拥有对视图中一小部分文档的访问权限时(销售或 HR 应用程序中可能出现这种情况),尤其如此。最佳解决方案仍然是使用 Show single category 来创建嵌入视图。通常这比打开文档上完全没有 Reader 限制的原始视图要快。
另外,可以对视图进行分类,而且开始时折叠视图。这将提高速度,尽管可能会导致前面讨论过的问题;即用户可以看到类别,但是在该类别中看不到任何文档。在某些情况下,将数据分解到多个视图中并将用户引导到正确视图很有意义。例如,如果用户单击导航中的 Regional Sales,而您可能有一个检查 @UserRoles 的公式,就会打开适当的视图 Sales-US、Sales-APAC 等。
有关视图性能的更多信息,请参阅 developerWorks Lotus 文章 “Lotus Notes/Domino 7 应用程序性能:第 2 部分:优化数据库视图”。
|
故障检修
本节将解决在用户组和讨论会中频繁出现的两个故障检修主题。
多值 Reader Names 字段
如果在表单中将 Reader Names 字段设置为单个值,后来又决定添加其他值,那么可以通过编写添加这些附加值的代理来实现上述操作。到目前为止没有出现问题,但是当用户编辑并保存文档时,表单仍会将该字段作为单值处理,而不是多值,因此可能会使 Reader Names 字段变得毫无用处。
例如,假定将 [HR] 角色添加到 Reader Names 字段。一年以后,您意识到将 [ProdDev] 角色也放入该字段很有意义。您编写代理来添加该值,并对拥有 [ProdDev] 角色但不拥有 [HR] 角色的用户进行了测试,一切看起来很正常。但是如果忘记更改表单上的字段属性,那么下一次有人使用该表单保存文档时,Reader 值将类似 “[HR], [ProdDev]”,而不是 “[HR]”“[ProdDev]”。换句话说,现在 Reader Names 字段将查找名为 [HR], [ProdDev] 的人或组(其中逗号只是名称的一部分,而不是值分隔符),因此没有人或组拥有该文档的访问权限。
避免此类问题的简单方法是始终将 Reader Names/Author 字段设置为多值。
恢复隐藏的文档
如果在文档上使用 Reader Names 字段,而且不经意地使一些文档对于所有用户来说都无法访问(例如前面所述,因插入多个条目,而产生一个无效的条目),则可以使用 Full Access Administration 模式(参见图 7)来打开数据库并恢复那些文档。事前创建一个应用了适当的 Reader 值的代理,然后处于 Full Access Administration 模式中时,可以触发该代理来修复数据。
在大多数组织中,只有一组经过挑选的管理员才能使用 Full Access Administration 模式,因此用户可能需要排队等候处理完成,但是起码可能实现不必操作服务器而是使用本地 Notes 客户机来绕过 Reader 安全。
|
结束语
希望本文有助于尽可能轻松高效地计划和实现 Reader Names 字段。它是个卓越的特性,也是个很好的安全措施,并且只要提前配置好各方面内容,就很容易实现和维护。只需要记住关键的一点:提前配置各方面内容。如果这样做了,则您在使用 Lotus Notes/Domino 中的强大特性时,将获得完美体验。