如何清理继承的访问权限

本文介绍如何在 Microsoft Dataverse 中表的级联配置更改时删除记录的继承访问权限。

现象

将 Reparent 或 Share 操作的表关系的级联行为更改为“无级联”后,可以继续访问应删除的相关记录。

用户可能会报告他们对记录具有意外访问权限。 可通过两种方式验证对相关记录的访问:使用 “检查访问 ”功能或 RetrieveAccessOrigin 消息。

使用“检查访问”功能

使用模型驱动应用中的 “检查访问 ”功能来检查谁有权访问记录。 管理员可以使用此功能来检查有权访问记录的单个用户或所有用户。

使用访问检查器时,会看到用户具有访问权限的原因列表。 其中一些原因表示由于对相关记录的访问权限而授予了共享。 例如:

  • 记录与我共享,因为我有权访问相关记录。
  • 记录是与团队(s)共享的,我是因为团队有权访问相关记录。

使用 RetrieveAccessOrigin 消息

开发人员可以使用 RetrieveAccessOrigin 消息来检测哪些用户有权访问记录。 此消息返回一个句子,描述用户为何有权访问。 以下任何结果都表示由于共享相关记录而授予了访问权限:

PrincipalId is owner of a parent entity of object (<record ID>)
PrincipalId is member of team (<team ID>) who is owner of a parent entity of object (<record ID>)
PrincipalId is member of organization (<organization ID>) who is owner of a parent entity of object (<record ID>)
PrincipalId has access to (<parent record ID>) through hierarchy security. (<parent record ID>) is owner of a parent entity of object (<record ID>)

有关详细信息,请参阅 “确定用户为何有权使用代码访问”。

原因

表关系级联行为发生更改时,Dataverse 会启动异步作业以删除以前授予的访问权限用户。 但是,此作业可能会失败,导致用户保留访问权限。

解决方法

解决此问题的第一步是重新创建系统作业以删除访问权限。 如果作业失败,开发人员可以使用 ResetInheritedAccess 消息将更改应用到指定的记录集。

重新创建系统作业以删除访问权限

开发人员可以使用 CreateAsyncJobToRevokeInheritedAccess 消息再次尝试创建异步作业。

使用 Microsoft.Xrm.Sdk.Messages.CreateAsyncJobToRevokeInheritedAccessRequest 类

/// <summary>
/// Creates and executes an asynchronous cleanup job to revoke inherited access granted through cascading inheritance.
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="relationshipSchemaName">The schema name of the entity relationship.</param>
public static void CreateAsyncJobToRevokeInheritedAccessExample(IOrganizationService service, string relationshipSchemaName)
{
    var request = new Microsoft.Xrm.Sdk.Messages.CreateAsyncJobToRevokeInheritedAccessRequest()
    {
        RelationshipSchema = relationshipSchemaName
    };

    service.Execute(request);
}

详细了解如何将消息与 SDK for .NET 配合使用。

该操作将创建名为 RevokeInheritedAccess CreateAsyncJobToRevokeInheritedAccess 的新异步作业。 可以监视此作业的成功。 有关详细信息,请参阅 监视系统作业使用代码管理系统作业。

重置继承的访问权限

如果 重新创建系统作业以删除访问权限 失败,则具有系统管理员或系统定制器权限的开发人员可以使用 ResetInheritedAccess 该消息以匹配记录的子集为目标。 可能需要多次使用此消息来删除对所有记录的访问权限。

/// <summary>
/// Resets the inherited access for the matching records.
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance to use.</param>
/// <param name="fetchXml">The fetchxml query.</param>
public static void OutputResetInheritedAccess(IOrganizationService service, string fetchXml)
{
    var parameters = new ParameterCollection()
    {
        { "FetchXml", fetchXml}
    };

    var request = new OrganizationRequest()
    {
        RequestName = "ResetInheritedAccess",
        Parameters = parameters
    };

    var response = service.Execute(request);

    Console.WriteLine(response.Results["ResetInheritedAccessResponse"]);
}

详细了解如何将消息与 SDK for .NET 配合使用。

如果记录不多,则 ResetInheritedAccess 消息会尝试同步执行。 然后值 ResetInheritedAccessResponse 以 . 结尾 ExecutionMode : Sync。 如果有许多匹配记录,则操作需要更长的时间,并且值以结尾 ExecutionMode : Async。 已创建名为 Denormalization_PrincipalObjectAccess_principalobjectaccess:<caller ID> 的系统作业,可以监视该作业的成功。 有关详细信息,请参阅 监视系统作业使用代码管理系统作业。

ResetInheritedAccess 消息需要 FetchXml 查询来标识记录。 此查询必须满足以下要求:

  • principalobjectaccess使用 (POA) 表。
  • principalobjectaccessid 返回列。
  • 不得包含任何 link-entity 元素。 不能将联接添加到另一个表。
  • 仅筛选表的 principalobjectaccess 列。

此表作为 principalobjectaccess 实体类型可供 Web API 使用。 它不包括在 Dataverse 表/实体引用 中,因为 POA 表不支持任何类型的直接数据修改操作。 需要知道此表的列以组成 FetchXml 查询。

POA 表列

只需使用这些列编写 FetchXml 查询。

逻辑名称 类型​​ 说明
accessrightsmask Integer 包含主体直接拥有的访问权限的组合 AccessRights 枚举 成员值。
changedon DateTime 主体访问记录的最后一个日期已更改。
inheritedaccessrightsmask Integer 包含由于继承而应用的访问权限的组合 AccessRights 枚举 成员值。
objectid 唯一标识符 主体有权访问的记录的 ID。
objecttypecode Integer 对应于 表的 EntityMetadata.ObjectTypeCode 值。 对于不同的环境,此值不一定相同。 对于自定义表,会根据创建表的顺序分配该表。 若要获取此值,可能需要查看表的元数据。 有几个社区工具可以找到这一点。 下面是来自Microsoft的解决方案: 浏览环境中的表定义。
principalid 唯一标识符 有权访问的用户或团队的 ID。
principalobjectaccessid 唯一标识符 POA 表的主键。
principaltypecode Integer 主体的类型代码。 SystemUser = 8, Team = 9。

以下 AccessRights 枚举 成员值适用于这些 accessrightsmask 值和 inheritedaccessrightsmask 列:

访问类型 说明
None 0 无访问权限。
Read 1 读取记录的权利。
Write 2 更新记录的权利。
Append 4 将指定记录追加到另一条记录的右侧。
AppendTo 16 将另一条记录追加到指定记录的右侧。
Create 32 创建记录的权利。
Delete 65,536 删除记录的权利。
Share 262,144 共享记录的权利。
Assign 524,288 向其他用户或团队分配指定记录的权利。

你可能会发现该值 inheritedaccessrightsmask 通常为 135,069,719。 此值包括除上述所有访问类型之外 Create的所有访问类型,这并非必要,因为这些权限仅适用于已创建的记录。

FetchXml 示例

本部分包括可用于消息的 FetchXml 查询的 ResetInheritedAccess 一些示例。 有关详细信息,请参阅 使用 FetchXML 构造查询

重置为特定帐户授予特定用户的继承访问权限
<fetch>
    <entity name="principalobjectaccess">
        <attribute name="principalobjectaccessid"/>
        <filter type="and">
            <condition attribute="principalid" operator="eq" value="9b5f621b-584e-423f-99fd-4620bb00bf1f" />
            <condition attribute="objectid" operator="eq" value="B52B7A48-EAFB-ED11-884B-00224809B6C7" />
        </filter>
    </entity>
</fetch>
为指定对象类型的所有子行重置给定的继承访问权限
<fetch>
    <entity name="principalobjectaccess">
        <attribute name="principalobjectaccessid"/>
        <filter type="and">
            <condition attribute="objecttypecode" operator="eq" value="10042" />
        </filter>
    </entity>
</fetch>
重置针对所有对象类型的指定用户授予的继承访问权限
<fetch>
    <entity name="principalobjectaccess">
        <attribute name="principalobjectaccessid"/>
        <filter type="and">
            <condition attribute="principalid" operator="eq" value="9b5f621b-584e-423f-99fd-4620bb00bf1f" />
        </filter>
    </entity>
</fetch>