6

在插件上下文中,有两个用户 ID,

  1. InitiatingUserId它返回实际触发插件的用户的 ID。
  2. UserId它返回插件实际运行的用户的用户 ID。(这是注册插件时指定的用户,或者是主叫用户,如果它被注册为作为主叫用户运行)

但我对第三个用户 ID 感兴趣,即执行调用的 OrganizationServiceProxy 的模拟用户 ID。

假设我有一个使用 CRM 系统管理员 AD 帐户运行的 ASP.Net 网站,并且对 CRM 进行的任何调用都使用模拟,查找当前登录到该站点的人的 CRM 用户 ID。

这对于选择和更新非常有用,用户只能看到\更新他们有权访问的内容。但是...如果我创建一个在更新特定实体时触发的插件,我如何从插件中查找 Asp 网站上模拟用户的用户 ID?

4

3 回答 3

3

据我对这种情况的理解,您可以检索模拟用户的用户 ID,但不能检索经过身份验证的用户。下面列出了一些场景,希望能阐明行为(在 UR11 和 UR12 中测试):

  1. 以用户 A身份向 CRM 进行身份验证,冒充用户B。插件未注册以模拟任何特定用户(即ImpersonatingUserId插件步骤设置为null(从插件注册工具中,“在用户上下文中运行”将设置为“调用用户”)。示例将以用户 AOrganizationServiceProxy身份验证,其中是用户 BproxyService.CallerId
    • PluginContext.UserId=用户 B
    • PluginContext.InitiatingUserId=用户 B
    • createdonbehalfby(或modifiedonbehalfby) =用户 A
  2. 以用户 A身份向 CRM 进行身份验证,冒充用户B。插件注册为模拟用户 C。(即插件步骤的 ImpersonatingUserId 设置为用户 C(从插件注册工具中,“在用户上下文中运行”将设置为用户 C))。示例将以User AOrganizationServiceProxy身份进行身份验证,其中是User BproxyService.CallerId
    • PluginContext.UserId=用户 C
    • PluginContext.InitiatingUserId=用户 B
    • createdonbehalfby(或modifiedonbehalfby) =用户 A

场景 #1 让我有点困惑,因为我隐约记得工作方式不同。这必须意味着当设置CallerId属性时,模拟发生在与场景 #2 不同的位置。但是,您可以看到在场景 #2 中,我们似乎达到了您的预期结果。

我用来产生这个结果的步骤是:

  1. 创建控制台应用程序并引用Microsoft.Xrm.SdkMicrosoft.Crm.Sdk.Proxy. 实例化一个新OrganizationServiceProxy对象,其中经过身份验证的用户是User A。将 设置为CallerId代表用户 B的 Guid 。
  2. 创建一个超级简单的插件,它在第一次出现时抛出异常,如下所示:

    throw new Exception(string.Format("Initiating Id: {0}, User Id: {1}", 
        context.InitiatingUserId, 
        context.UserId));
    
于 2013-05-27T17:07:27.043 回答
0

只是想澄清 GotDibb 的数据是正确的,即使我的问题与之相矛盾。

我创建了一个 UserIdTest 插件如下

public void Execute(IServiceProvider serviceProvider)
{
    var context = serviceProvider.GetContext();
    var service = serviceProvider.GetService(context);
    var iUser = service.Retrieve("systemuser", context.InitiatingUserId, new ColumnSet("fullname"));
    var uUser = service.Retrieve("systemuser", context.UserId, new ColumnSet("fullname"));
    throw new Exception(string.Format("Initiating: {0}, User: {1}", 
        iUser.GetAttributeValue<string>("fullname"),
        uUser.GetAttributeValue<string>("fullname")));
}

我进行了与 GotDibbs 相同的测试,得到了相同的答案,这让我感到困惑,因为如果我没有以某种方式得到不同的答案,我就不会问这个问题。但后来我意识到我看到的问题是由递归插件引起的。

对插件的第一次调用按预期工作,但是当插件触发对插件的另一个调用时,它使用了插件的上下文用户凭据(这是有道理的)并丢失了模拟用户 ID 的凭据。这是一张表格,希望能帮助澄清发生了什么

首先是初始插件调用:

+--------------------+------------ +----------------------+----------------------------------------+
|    Org Service     | Org Service |    Plugin Step Run   |               Results                  |
| Client Credentials |  CallerId   |   in User's Context  |                                        |
+--------------------+------------ +----------------------+----------------------------------------+
|                    |             |                      | InitiaitingUser : ServiceAccount       |
| ServiceAccount     | None        | PluginServiceAccount |                                        |
|                    |             |                      | UserId : PluginServiceAccount          |
+--------------------+------------ +----------------------+----------------------------------------+
|                    |             |                      | InitiaitingUser : UserBob              |
| ServiceAccount     | UserBob     | PluginServiceAccount |                                        |
|                    |             |                      | UserId : PluginServiceAccount          |
+--------------------+------------ +----------------------+----------------------------------------+

第二个插件深度> 1

+--------------------+------------ +----------------------+----------------------------------------+
|    Org Service     | Org Service |    Plugin Step Run   |               Results                  |
| Client Credentials |  CallerId   |   in User's Context  |                                        |
+--------------------+-------------+----------------------+----------------------------------------+
|                    |             |                      | InitiaitingUser : PluginServiceAccount |
| ServiceAccount     | None        | PluginServiceAccount |                                        |
|                    |             |                      | UserId : PluginServiceAccount          |
+--------------------+-------------+----------------------+----------------------------------------+
|                    |             |                      | InitiaitingUser : PluginServiceAccount |
| ServiceAccount     | UserBob     | PluginServiceAccount |                                        |
|                    |             |                      | UserId : PluginServiceAccount          |
+--------------------+-------------+----------------------+----------------------------------------+
于 2013-06-12T17:03:50.590 回答
-1

同样的问题也与 CRM 2013 相关,并且可能具有相同的解决方案:

以注册插件在调用用户的上下文下执行的场景为例,插件执行上下文的 InitiatingUserId 和 UserId 值将是相同的。

即使客户端通过覆盖 CallerId 建立连接也是如此 - 在这种情况下,两个值都将表示指定的 CallerId 值,而不是经过身份验证的用户的身份。

那么如何在插件中获取实际调用者的身份呢?后期阶段很简单,只需在后期执行图像中检查 createdonbehalfby 或 modifiedonbehalfby 即可。预操作并不明显,因为这些值在任何地方都不存在,但诀窍很简单。

在插件内部,建立一个新的 IOrganizationService,其中 UserId 为 NULL,而不是 context.UserId 或 context.InitiatingUserId,而只是 null。然后使用该服务,执行 WhoAmI 请求,响应将包含执行服务调用的经过身份验证的用户的 GUID,而不是指定的 CallerId 的标识。

事实证明, IOrganizationServiceFactory 实际上有一个包含此值 (AdministratorId) 的私有字段,但由于它是私有的,因此无法读取,因此此解决方法将以额外开销为代价。

于 2015-01-20T00:15:40.020 回答