如何清理继承的访问权限

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

症状

在“重新父级”或“共享”操作的表关系的级联行为更改为“无级联”后,可以继续访问应删除的相关记录。

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

使用“检查访问”功能

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

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

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

使用 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 配合使用

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

重置继承的访问权限

如果 重新创建系统作业以删除访问权限 失败,则具有系统管理员或系统定制员权限的开发人员可以使用该 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 会尝试同步执行。 然后,值 ResetInheritedAccessResponseExecutionMode : Sync结尾。 如果存在许多匹配的记录,则操作需要更长的时间,并且值以 ExecutionMode : Async结尾。 将创建一个名为 Denormalization_PrincipalObjectAccess_principalobjectaccess:<caller ID> 的系统作业,可以监视该作业是否成功。 有关详细信息,请参阅 监视系统作业 或使用 代码管理系统作业

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

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

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

POA 表列

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

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

以下 AccessRights 枚举 成员值适用于 accessrightsmaskinheritedaccessrightsmask 列:

访问类型 说明
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 示例

本部分包含一些可用于 ResetInheritedAccess 消息的 FetchXml 查询示例。 有关详细信息,请参阅 使用 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>