如何清理继承的访问权限
本文介绍如何在 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);
}
该 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"]);
}
当匹配记录不多时,消息 ResetInheritedAccess
会尝试同步执行。 然后,值 ResetInheritedAccessResponse
以 ExecutionMode : 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 枚举 成员值适用于 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 示例
本部分包含一些可用于 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>