我们有一个带有汇总 13 的本地 CRM。一些表单需要填充来自多个来源并需要进行预处理的外部数据。为此,我们开发了一个自定义 WCF 服务,该服务在与 CRM 相同的服务器上运行,并作为 CRM 网站中的虚拟应用程序托管在 IIS 中(以避免跨域脚本问题),并将 REST 端点暴露给运行在客户关系管理表格。javascript 发出请求,服务收集和处理数据,然后用一些漂亮的简单 JSON 回复 javascript。
由于我们需要的一些数据来自 CRM 本身,我们认为我们会让服务也收集这些数据(使用 CRM 的 SOAP 端点),而不是直接从 javascript 向 CRM Web 服务发出请求。我们在 IIS 中设置了直通身份验证,因此我们的自定义应用程序在模拟登录到 CRM 的用户时向 CRM 发出请求。
大多数时候,这一切都很好。然而,一旦我们有更多的测试人员,我们开始注意到 CRM 偶尔会停止为某些用户回复我们的服务,从而引发异常。如果该用户关闭浏览器并重新打开它,然后尝试完全相同的操作,一切都会重新开始工作。我在 CRM 服务器上打开了跟踪,发现发生这种情况时,CRM 正在记录“Crm 异常:消息:用户 ID 无效。,错误代码:-2147214049”。下面的完整跟踪:
[2013-09-10 08:54:14.492] Process: w3wp |Organization:00000000-0000-0000-0000-000000000000 |Thread: 69 |Category: Exception |User: 00000000-0000-0000-0000-000000000000 |Level: Error |ReqId: 4b901457-a545-4844-9ce8-b017d3833087 | CrmException..ctor ilOffset = 0x36
at CrmException..ctor(Int32 errorCode, Object[] arguments) ilOffset = 0x36
at SecurityLibrary.GetPrivilegedUserCallerAndBusinessGuidsFromThread(WindowsIdentity identity, IOrganizationContext context) ilOffset = 0x6F
at SecurityLibrary.GetCallerAndBusinessGuidsFromThread(WindowsIdentity identity, Guid organizationId, LocatorServiceContext locatorServiceContext) ilOffset = 0x56
at UserManagementFactory.ValidateSpecialUser(WindowsIdentity identity, Guid organizationId) ilOffset = 0x1E
at WindowsIdentityAuthorizationManager.Authenticate(OperationContext operationContext) ilOffset = 0x185
at WindowsIdentityAuthorizationManager.CheckAccessCore(OperationContext operationContext) ilOffset = 0x22
at AuthorizationBehavior.Authorize(MessageRpc& rpc) ilOffset = 0x28
at ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) ilOffset = 0x293
at MessageRpc.Process(Boolean isOperationContextSet) ilOffset = 0x62
at ChannelHandler.DispatchAndReleasePump(RequestContext request, Boolean cleanThread, OperationContext currentOperationContext) ilOffset = 0x1D7
at ChannelHandler.HandleRequest(RequestContext request, OperationContext currentOperationContext) ilOffset = 0xF1
at ChannelHandler.AsyncMessagePump(IAsyncResult result) ilOffset = 0x21
at AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) ilOffset = 0x0
at AsyncResult.Complete(Boolean completedSynchronously) ilOffset = 0xC2
at ReceiveItemAndVerifySecurityAsyncResult`2.InnerTryReceiveCompletedCallback(IAsyncResult result) ilOffset = 0x55
at AsyncThunk.UnhandledExceptionFrame(IAsyncResult result) ilOffset = 0x0
at AsyncResult.Complete(Boolean completedSynchronously) ilOffset = 0xC2
at AsyncQueueReader.Set(Item item) ilOffset = 0x21
at InputQueue`1.Dispatch() ilOffset = 0x121
at ScheduledOverlapped.IOCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped) ilOffset = 0x22
at IOCompletionThunk.UnhandledExceptionFrame(UInt32 error, UInt32 bytesRead, NativeOverlapped* nativeOverlapped) ilOffset = 0x5
at _IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP) ilOffset = 0x3C
>Crm Exception: Message: The user Id is invalid., ErrorCode: -2147214049
[2013-09-10 08:54:14.508] Process: w3wp |Organization:00000000-0000-0000-0000-000000000000 |Thread: 69 |Category: Platform.Sdk |User: 00000000-0000-0000-0000-000000000000 |Level: Error |ReqId: 4b901457-a545-4844-9ce8-b017d3833087 | ServiceModelTraceRedirector.TraceData ilOffset = 0x45
><TraceRecord xmlns="http://schemas.microsoft.com/2004/10/E2ETraceEvent/TraceRecord" Severity="Error"><TraceIdentifier>http://msdn.microsoft.com/en-CA/library/System.ServiceModel.Diagnostics.TraceHandledException.aspx</TraceIdentifier><Description>Handling an exception.</Description><AppDomain>/LM/W3SVC/1/ROOT-6-130232384646037254</AppDomain><Exception><ExceptionType>Microsoft.Crm.CrmException, Microsoft.Crm.Core, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</ExceptionType><Message>The user Id is invalid.</Message><StackTrace> at Microsoft.Crm.BusinessEntities.SecurityLibrary.GetPrivilegedUserCallerAndBusinessGuidsFromThread(WindowsIdentity identity, IOrganizationContext context)
> at Microsoft.Crm.BusinessEntities.SecurityLibrary.GetCallerAndBusinessGuidsFromThread(WindowsIdentity identity, Guid organizationId, LocatorServiceContext locatorServiceContext)
> at Microsoft.Crm.Authentication.UserManagementFactory.ValidateSpecialUser(WindowsIdentity identity, Guid organizationId)
> at Microsoft.Crm.Authentication.WindowsIdentityAuthorizationManager.Authenticate(OperationContext operationContext)
> at Microsoft.Crm.Authentication.WindowsIdentityAuthorizationManager.CheckAccessCore(OperationContext operationContext)
> at System.ServiceModel.Dispatcher.AuthorizationBehavior.Authorize(MessageRpc&amp; rpc)
> at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc)
> at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</StackTrace><ExceptionString>Microsoft.Crm.CrmException: The user Id is invalid.
> at Microsoft.Crm.BusinessEntities.SecurityLibrary.GetPrivilegedUserCallerAndBusinessGuidsFromThread(WindowsIdentity identity, IOrganizationContext context)
> at Microsoft.Crm.BusinessEntities.SecurityLibrary.GetCallerAndBusinessGuidsFromThread(WindowsIdentity identity, Guid organizationId, LocatorServiceContext locatorServiceContext)
> at Microsoft.Crm.Authentication.UserManagementFactory.ValidateSpecialUser(WindowsIdentity identity, Guid organizationId)
> at Microsoft.Crm.Authentication.WindowsIdentityAuthorizationManager.Authenticate(OperationContext operationContext)
> at Microsoft.Crm.Authentication.WindowsIdentityAuthorizationManager.CheckAccessCore(OperationContext operationContext)
> at System.ServiceModel.Dispatcher.AuthorizationBehavior.Authorize(MessageRpc&amp; rpc)
> at System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc&amp; rpc)
> at System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)</ExceptionString></Exception></TraceRecord>
在我看来,某种安全令牌或某种缓存凭据会过期或以某种方式失效,并且我们的应用程序无法再向 CRM 进行身份验证。重新打开 IE 可以解决这个问题。我们还没有找到可靠地重现这种情况的方法,但它经常发生,足以引起用户的关注。有人有想法么?