【问题标题】:How to Get the Impersonated User Id in a Plugin?如何在插件中获取模拟用户 ID?
【发布时间】:2013-05-19 09:01:35
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 我读了你的问题 4 次,如果我理解你有这种情况:用户 DOMAIN\SMITH 登录在运行在 DOMAIN\IAMSYSADMIN (应用程序池)下的站点内,并在运行调用的触发插件内用户 DOMAIN\PLUGINUSER,您想知道初始用户是 DOMAIN\SMITH 而不是 DOMAIN\SPECTER,对吧?
  • 此信息应在 InitiatingUserId 中可用。你得到任何其他价值吗?总有 WhoAmI() 请求可能对您的情况有所帮助。
  • @MarioZG 在我的示例中,InitiatingUserId 将是应用程序池用户的 id,而不是模拟用户。 WhoAmI 请求将返回运行插件的用户的 ID。
  • @GuidoPreite 如果 DOMAIN\SPECTOR 您的意思是 DOMAIN\IAMSYSADMIN,那么可以。相信你理解正确。
  • 我的意思是你想知道登录站点的用户(DOMAIN\SMITH 或 DOMAIN\SPECTER(网站的另一个用户),因为你已经知道应用程序池是 DOMAIN\ IAMSYSADMIN 是您从 InitiatingUserId 获得的,您想再深入一层。

标签: asp.net c#-4.0 plugins dynamics-crm-2011 dynamics-crm


【解决方案1】:

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

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

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

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

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

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

【讨论】:

    【解决方案2】:

    只是想澄清 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          |
    +--------------------+-------------+----------------------+----------------------------------------+
    

    【讨论】:

      【解决方案3】:

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

      1. 作为 用户 A 向 CRM 进行身份验证,冒充 用户 B。插件未注册以模拟任何特定用户(即插件步骤的ImpersonatingUserId 设置为null(从插件注册工具中,“在用户上下文中运行”将设置为“调用用户”)。示例将与OrganizationServiceProxy 被验证为 User A,其中 proxyService.CallerIdUser B
        • PluginContext.UserId = 用户 B
        • PluginContext.InitiatingUserId = 用户 B
        • createdonbehalfby(或modifiedonbehalfby)= 用户A
      2. 作为 用户 A 向 CRM 进行身份验证,冒充 用户 B。插件已注册以模拟 用户 C。 (即插件步骤的 ImpersonatingUserId 设置为用户 C(从插件注册工具中,“在用户上下文中运行”将设置为用户 C))。例如,OrganizationServiceProxy 被验证为 User A,其中 proxyService.CallerIdUser B
        • 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));
        

      【讨论】:

      • 这是针对 CRM 4.0 的吗?我没有为 CRM 2011 找到任何 ImpersonatingUserId。我无法重新创建您的场景 #1。
      • @Daryl 这是 2011 年的。让我今天早上试着做一个样本,我会更新这个问题。您在哪里寻找 ImpersonatingUserId 而没有找到它?插件注册或组织服务设置?
      • @Daryl 我进行了更新以阐明插件注册工具中的 ImpersonatingUserId 等同于什么。让我知道这是否不能为您澄清事情。
      • 谢谢,澄清了。我发誓我尝试了场景 1,并且插件上下文中的 UserIdInitiaitingUserId 都是 UserA。你能验证你的步骤吗?
      • @Daryl 我可以发誓我看到了不同的东西。我已经用我在 UR11 和 UR12 的实际测试中看到的内容更新了答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-27
      • 1970-01-01
      • 1970-01-01
      • 2017-04-30
      • 2011-07-06
      • 1970-01-01
      • 2019-12-26
      相关资源
      最近更新 更多