精通 Salesforce 共享规则:架构师视角下的可扩展性与安全性指南

背景与应用场景

在 Salesforce 平台的设计哲学中,数据安全与访问控制是基石。作为一名 Salesforce 架构师,我们设计的任何解决方案都必须建立在一个健壮、可扩展且易于维护的安全模型之上。这个模型的起点是组织范围默认设置 (Organization-Wide Defaults, OWD),它定义了整个组织中最严格的记录访问级别。OWD 的原则是“先锁定,再授权”,即默认情况下,用户只能访问他们自己的记录。

然而,在现实的商业场景中,这种严格的隔离是远远不够的。协作是业务成功的关键。例如,一个区域的销售团队可能需要查看另一个区域的特定行业客户,以便进行协同销售;一个支持团队可能需要访问由特定产品专家团队拥有的高优先级案例;或者,财务部门需要对所有已签约的业务机会(Opportunity)拥有只读权限以进行审计。这些跨越了用户所有权和角色层级的横向访问需求,正是 Sharing Rules(共享规则) 发挥核心作用的地方。

共享规则是 Salesforce 数据访问模型中,继 OWD 和角色层级 (Role Hierarchy) 之后,用于扩展记录访问权限的关键工具。如果说角色层级解决了“垂直”方向(即上级对下级)的访问问题,那么共享规则则优雅地解决了“水平”或“例外”的访问需求。它允许我们基于可预测、稳定的业务逻辑,自动地将记录的访问权限授予那些在 OWD 和角色层级下本无权访问的用户或用户组。作为架构师,深刻理解共享规则的原理、性能影响和最佳实践,对于构建一个既安全又高效的企业级 Salesforce 实施至关重要。


原理说明

从架构层面理解共享规则,不能仅仅停留在 UI 配置的层面,而必须深入其底层机制。当一个对象的 OWD 设置为“私有 (Private)”或“公共只读 (Public Read Only)”时,Salesforce 会为该对象创建一个关联的 Share Object(共享对象)。例如,对于 Account 对象,会有一个名为 AccountShare 的对象;对于自定义对象 MyCustomObject__c,则会有一个 MyCustomObject__Share 对象。

这个共享对象本质上是一个访问控制列表 (Access Control List, ACL)。它的每一条记录都定义了“哪个记录 (ParentId)”被共享给了“哪个用户或组 (UserOrGroupId)”,以及授予了什么样的“访问级别 (AccessLevel)”(如 Read 或 Read/Write),并且记录了共享的原因 (RowCause)。

共享规则的工作原理就是在这个共享对象中自动创建和管理记录。当我们定义一条共享规则时,Salesforce 会在后台执行一个进程,评估所有符合条件的记录,并在对应的共享对象中插入相应的共享记录。这个过程被称为 Sharing Recalculation(共享重算)。共享重算是一个非常关键且对性能影响显著的操作,它会在创建/更新共享规则、更改角色层级、更改用户所属的公共组 (Public Group) 或更改 OWD 时被触发。

共享规则主要分为两种类型:

1. 基于所有者的共享规则 (Owner-based Sharing Rules)

这种规则基于记录的所有者。它将由特定公共组、角色或区域的成员所拥有的记录,共享给其他公共组、角色或区域的成员。例如,“将‘美国东部销售’角色成员拥有的所有客户,以读写权限共享给‘渠道合作伙伴’公共组”。

2. 基于条件的共享规则 (Criteria-based Sharing Rules)

这种规则更为灵活,它不关心记录的所有者是谁,而是基于记录本身的字段值。只要记录满足预设的条件,它就会被共享。例如,“将所有‘行业’字段为‘金融服务’且‘年收入’大于一百万美元的客户,以只读权限共享给‘大客户战略’公共组”。

对于架构师而言,理解 RowCause 至关重要。在共享对象中,这个字段说明了为什么会存在这条共享记录。例如,RowCause 的值为 Rule 表示这条共享记录是由共享规则创建的;值为 Manual 表示是用户手动共享的;值为 Owner 表示是记录所有者固有的访问权限。这对于调试复杂的访问权限问题非常有帮助。


示例代码

在企业级的 Salesforce 实施中,我们很少会手动在生产环境中创建和修改共享规则。作为架构师,我们推崇的是通过元数据驱动的部署方式,例如使用 Salesforce DX 或 Ant 迁移工具,以确保环境的一致性和变更的可追溯性。因此,以下示例将展示如何在元数据 XML 文件中定义共享规则,而不是展示 Apex 代码(Apex 用于更动态的 Apex Managed Sharing)。

以下是 Opportunity.sharingRules 文件的一个示例,它定义了一条基于所有者的规则和一条基于条件的规则。这段代码可以直接包含在你的元数据包中进行部署。

<?xml version="1.0" encoding="UTF-8"?>
<SharingRules xmlns="http://soap.sforce.com/2006/04/metadata">

    <!-- 示例 1: 基于所有者的共享规则 -->
    <!-- 这条规则将由“西海岸销售团队”公共组的成员拥有的所有业务机会 -->
    <!-- 以“读/写”权限共享给“战略客户经理”角色及其下属角色。 -->
    <sharingOwnerRules>
        <fullName>Share_West_Coast_Opps_With_Strategic_AMs</fullName>
        <label>Share West Coast Opps With Strategic AMs</label>
        <sharedFrom>
            <!-- 定义记录所有者所在的组 -->
            <group>West_Coast_Sales_Team</group>
        </sharedFrom>
        <sharedTo>
            <!-- 定义被共享到的角色和下属角色 -->
            <roleAndSubordinates>Strategic_Account_Manager</roleAndSubordinates>
        </sharedTo>
        <!-- 定义业务机会的访问级别 -->
        <opportunityAccessLevel>ReadWrite</opportunityAccessLevel>
        <!-- 定义关联客户的访问级别 -->
        <accountAccessLevel>Read</accountAccessLevel>
        <description>Allows strategic account managers to collaborate on deals owned by the west coast team.</description>
    </sharingOwnerRules>

    <!-- 示例 2: 基于条件的共享规则 -->
    <!-- 这条规则将所有阶段为“Closed Won”的业务机会 -->
    <!-- 以“只读”权限共享给“财务审计”公共组。 -->
    <sharingCriteriaRules>
        <fullName>Share_Closed_Won_Opps_With_Finance</fullName>
        <label>Share Closed Won Opps With Finance</label>
        <sharedTo>
            <!-- 定义被共享到的公共组 -->
            <group>Finance_Audit_Team</group>
        </sharedTo>
        <criteriaItems>
            <!-- 条件字段:阶段 (StageName) -->
            <field>StageName</field>
            <!-- 操作:等于 (equals) -->
            <operation>equals</operation>
            <!-- 条件值:Closed Won -->
            <value>Closed Won</value>
        </criteriaItems>
        <!-- 定义业务机会的访问级别 -->
        <opportunityAccessLevel>Read</opportunityAccessLevel>
        <!-- 定义关联客户的访问级别 -->
        <accountAccessLevel>Read</accountAccessLevel>
        <description>Provides read-only access to all closed won opportunities for auditing purposes.</description>
    </sharingCriteriaRules>

</SharingRules>

注意事项

作为架构师,在设计共享规则策略时,必须充分考虑其对整个系统性能和可维护性的影响。以下是一些关键的注意事项:

1. 性能与共享重算

共享重算是性能的最大考量点。在拥有数百万甚至数千万条记录的大数据量 (Large Data Volume, LDV) 环境中,一次完整的共享重算可能需要数小时甚至更长时间。在此期间,用户可能会遇到性能下降或记录锁定问题。因此,应尽量避免频繁更改共享规则、角色层级和 OWD。所有此类变更都应在业务低峰期进行,并经过充分的性能影响评估。

2. 所有权倾斜 (Ownership Skew)

当单个用户拥有大量(通常指超过 10,000 条)某个对象的记录时,就会出现所有权倾斜。如果这个用户在角色层级中的位置发生变动,或者涉及这个用户的共享规则被修改,系统需要为这个用户拥有的所有记录重新计算共享,这会给系统带来巨大压力,并可能导致记录锁定超时。设计解决方案时,应避免将大量记录分配给单个集成用户或队列,尽量将记录所有权分散。

3. 平台限制

Salesforce 对每个对象的共享规则数量有限制,默认为 300 条(包括所有者和条件规则),尽管可以通过联系 Salesforce 支持来提高此限制,但这通常是一个信号,表明你的共享模型可能过于复杂。架构师应将此限制作为设计约束,如果预见到会超出此限制,应及早考虑其他共享机制,如区域管理 (Territory Management) 或 Apex 托管共享 (Apex Managed Sharing)。

4. 访客用户共享规则 (Guest User Sharing Rules)

对于 Experience Cloud 站点中的未经身份验证的访客用户,Salesforce 实施了更严格的安全策略。你只能创建基于条件的共享规则来授予访客用户访问权限,并且规则的数量和功能受到严格限制。这是为了保护公共站点的安全性,防止数据泄露。

5. 维护的复杂性

随着业务的发展,共享规则的数量可能会迅速增加,形成一个复杂的、难以理解和调试的“共享之网”。每一条规则都应有明确的业务理由,并记录在案。优先使用公共组 (Public Groups) 而不是角色 (Roles) 来定义共享目标,因为公共组的成员可以灵活调整,而无需改变角色层级这个更具结构性的设置。


总结与最佳实践

共享规则是 Salesforce 数据安全模型中不可或缺的一部分,它提供了在严格的 OWD 基础上灵活扩展访问权限的能力。然而,强大的能力也伴随着巨大的责任。作为架构师,我们的目标是利用共享规则来满足业务需求,同时确保系统的长期健康、可扩展性和高性能。

以下是设计和实施共享规则时的最佳实践:

- 最小权限原则: 始终从最严格的 OWD 开始(通常是 Private),然后按需逐步开放访问权限。这是最安全、最可控的方法。

- 善用角色层级: 首先利用角色层级来解决所有垂直方向的访问需求。只有当角色层级无法满足需求时,才考虑使用共享规则。

- 优先使用公共组: 在共享规则的“共享给 (Shared To)”部分,尽可能使用公共组。这提供了极大的灵活性,因为管理员可以随时调整组成员,而无需触及共享规则本身或核心的角色层级结构。

- 保持规则简洁高效: 避免创建过多、过于复杂的共享规则。合并相似的规则,使用高效的条件(避免使用复杂的公式字段作为条件),并定期审查和清理不再需要的规则。

- 考虑替代方案: 对于非常复杂或动态的共享需求,共享规则可能不是最佳选择。应评估其他工具,例如: - Territory Management 2.0: 对于基于客户属性(如地理位置、行业、规模)的复杂销售团队结构,区域管理是更强大、更合适的解决方案。 - Apex Managed Sharing: 当共享逻辑依赖于无法通过标准规则表达的复杂业务流程或第三方数据时,可以通过 Apex 代码以编程方式创建和管理共享记录。

- 规划与文档: 在实施任何共享规则之前,进行全面的规划,并创建详细的文档,说明每条规则的目的、标准、所有者和受益者。这将成为未来维护和故障排查的宝贵资产。

最终,一个优秀的共享模型架构不是最复杂的,而是最简洁、最能清晰反映业务需求且对性能影响最小的模型。通过深思熟虑地运用共享规则,我们可以为企业构建一个既安全又协作的 Salesforce 环境。

评论

此博客中的热门博文

Salesforce Einstein AI 编程实践:开发者视角下的智能预测

Salesforce 登录取证:深入解析用户访问监控与安全

Salesforce Experience Cloud 技术深度解析:构建社区站点 (Community Sites)