在插件上下文中,有两个用户ID
InitiatingUserId
,它返回实际触发插件的用户的ID。UserId
返回插件实际运行的用户的用户ID。 (这是注册插件时指定的用户,或者调用用户,如果它已注册为主叫用户运行)但我对第三个用户ID感兴趣,该用户ID是执行该调用的OrganizationServiceProxy的模拟用户ID。
假设我有一个运行CRM系统管理员帐号的ASP.Net网站,以及对CRM进行的任何调用,使用模拟,查找当前登录该网站的人员的CRM用户ID。 / p>
这适用于选择和更新,用户只能看到\更新他们有权使用的权限。但是......如果我创建一个在特定实体更新时触发的插件,如何在插件中查找Asp网站上模拟用户的用户ID?
答案 0 :(得分:3)
就我对情况的理解而言,您可以检索模拟用户的用户ID,但不能检索经过身份验证的用户。下面列出了一些应该有希望澄清行为的场景(在UR11和UR12中测试):
ImpersonatingUserId
插件步骤设置为null
(从插件注册工具,“在用户的上下文中运行”将设置为“呼叫用户”)。示例将OrganizationServiceProxy
通过用户A 进行身份验证,其中proxyService.CallerId
为用户B 。
PluginContext.UserId
= 用户B PluginContext.InitiatingUserId
= 用户B createdonbehalfby
(或modifiedonbehalfby
)= 用户A
OrganizationServiceProxy
通过用户A 进行身份验证,其中proxyService.CallerId
为用户B 。
PluginContext.UserId
= 用户C PluginContext.InitiatingUserId
= 用户B createdonbehalfby
(或modifiedonbehalfby
)= 用户A 情景#1对我来说有点混乱,因为我依稀记得以不同的方式工作。这必须意味着当设置CallerId
属性时,模拟发生在与场景#2不同的位置。但是,您可以看到在场景#2中,我们似乎达到了您的预期结果。
我用来产生这个结果的步骤是:
Microsoft.Xrm.Sdk
和Microsoft.Crm.Sdk.Proxy
。实例化新的OrganizationServiceProxy
对象,其中经过身份验证的用户用户A 。将CallerId
设置为代表用户B 的Guid。创建一个超级简单的插件,它只会在第一次出现异常时引发异常:
throw new Exception(string.Format("Initiating Id: {0}, User Id: {1}",
context.InitiatingUserId,
context.UserId));
答案 1 :(得分: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进行了相同的测试,并得到了相同的答案,这让我很困惑,因为我不会问这个问题我是不是以某种方式得到了不同的答案。但后来我意识到我看到的问题是由递归插件引起的。
对插件的第一次调用按预期工作,但是当插件触发另一个插件调用时,它使用了插件的Context用户的凭据(这是有意义的)并丢失了模拟的用户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 |
+--------------------+------------ +----------------------+----------------------------------------+
插件深度的第二个&gt; 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 |
+--------------------+-------------+----------------------+----------------------------------------+
答案 2 :(得分:-1)
同样的问题在CRM 2013中也很重要,可能也有相同的解决方案:
在注册插件的情况下,在调用用户的上下文中执行,插件执行上下文的InitiatingUserId和UserId值都是相同的。
即使客户端通过覆盖CallerId建立连接也是如此 - 在这种情况下,两个值都表示指定的CallerId值,而不是经过身份验证的用户的身份。
那么如何在插件中获取实际的调用者身份?后期阶段很简单,只需在后执行图像中检查是否已创建或已修改为onbehalfby。操作前并不明显,因为这些值在任何地方都不存在,但技巧很简单。
在插件内部,建立一个新的IOrganizationService,其中UserId为NULL,而不是context.UserId或context.InitiatingUserId,而只是null。然后使用该服务,执行WhoAmI请求,响应将包含执行服务调用的经过身份验证的用户的GUID,而不是指定的CallerId的标识。
事实证明,IOrganizationServiceFactory实际上有一个包含此值的私有字段(AdministratorId),但由于它是私有的,因此无法读取,因此这种解决方法将以额外开销为代价。