如何清理继承的访问权限
本文介绍如何在 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>