CRM インストールでデータをより適切に表示するために、基本的に処理したい CRM データ (従業員の勤務時間) を読み取り、Telerik (Scheduler) を使用して読みやすい形式に変換する Azure Web サイトがあります。定期的な予定を使用します)。Telerik の予定は変換されないため、CRM への読み取り専用接続になります。
認証に固定ユーザーを使用して製品が正常に動作するようになりましたが、現在ログインしているユーザーを使用して認証したい場合、AD が関与する障害に遭遇します。以下のコードの currentUserId は、フォームからクエリ文字列を介して渡されます。
private OrganizationServiceProxy CreateOrganizationService(String serverAddress, String organizationName, Guid currentUserId)
{
var discoveryServiceUri = serverAddress.Contains("http") ? new Uri(String.Format("{0}/XRMServices/2011/Discovery.svc", serverAddress)) : new Uri(String.Format("http://{0}/XRMServices/2011/Discovery.svc", serverAddress));
System.Diagnostics.Trace.TraceInformation("current discoveryUri: " + discoveryServiceUri);
var credentials = new ClientCredentials();
// Get the user's logon credentials.
credentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
System.Diagnostics.Trace.TraceInformation("current user: " + CredentialCache.DefaultNetworkCredentials.UserName);
// Get the target organization.
var organizationUri = GetOrganizationAddress(organizationName, discoveryServiceUri, credentials, null);
System.Diagnostics.Trace.TraceInformation("current organization: " + organizationUri);
var serviceProxy = new OrganizationServiceProxy(organizationUri, null, credentials, null);
// This statement is required to enable early-bound type support.
serviceProxy.EnableProxyTypes();
if (currentUserId == Guid.Empty)
{
currentUserId = GetUserId(serviceProxy);
}
if (currentUserId != Guid.Empty)
serviceProxy.CallerId = currentUserId;
return serviceProxy;
}
上記のコードは、サーバー側で CRM 接続を作成するために使用されます。
private Uri GetOrganizationAddress(String organizationName, Uri discoveryServiceUri, ClientCredentials credentials, ClientCredentials deviceCredentials)
{
if (discoveryServiceUri == null)
throw new Exception("DiscoveryServiceUri is null. Please specify a valid configuration details to connect crm server.");
using (var serviceProxy = new DiscoveryServiceProxy(discoveryServiceUri, null, credentials, deviceCredentials))
{
// Obtain organization information from the Discovery service.
{
// Obtain information about the organizations that the system user belongs to.
System.Diagnostics.Trace.TraceInformation("getting organizationss now");
OrganizationDetailCollection orgs = DiscoverOrganizations(serviceProxy);
System.Diagnostics.Trace.TraceInformation(orgs.Count + " organizations discovered");
if (orgs.Count > 0)
{
int orgNumber = 0;
for (int n = 0; n < orgs.Count; n++)
{
if (orgs[n].UniqueName == organizationName || orgs[n].FriendlyName == organizationName)
{
orgNumber = n + 1;
System.Diagnostics.Trace.TraceInformation("orgs[n].UniqueName: " + orgs[n].UniqueName);
System.Diagnostics.Trace.TraceInformation("orgs[n].friendlyName: " + orgs[n].FriendlyName);
break;
}
}
if (orgNumber > 0 && orgNumber <= orgs.Count)
{
Version version = new Version(orgs[orgNumber - 1].OrganizationVersion);
System.Diagnostics.Trace.TraceInformation("version: " + version.Build);
// Return the organization Uri.
Uri uri = new Uri(orgs[orgNumber - 1].Endpoints[EndpointType.OrganizationService]);
System.Diagnostics.Trace.TraceInformation("uri:" + uri);
return uri;
}
throw new Exception(string.Format("The specified organization '{0}' does not exist.", organizationName));
}
throw new Exception(string.Format("You do not belong to any organizations on the specified server. DiscoveryServiceUri '{0}'", discoveryServiceUri.AbsoluteUri));
}
}
}
以下のコードは、問題が発生する場所です。
private OrganizationDetailCollection DiscoverOrganizations(IDiscoveryService service)
{
var orgRequest = new RetrieveOrganizationsRequest();
System.Diagnostics.Trace.TraceInformation("orgrequest made");
var orgResponse = (RetrieveOrganizationsResponse)service.Execute(orgRequest);
System.Diagnostics.Trace.TraceInformation("orgresponse retrieved: " + orgResponse);
System.Diagnostics.Trace.TraceInformation("orgResponse.details: " + orgResponse.Details);
return orgResponse.Details;
}
Execute(orgRequest) コマンドでうまくいきません。これを AD 認証の問題、つまり、資格情報が間違っているように見えることまで追跡しました。最初の方法で、(CRM ユーザー アカウントではなく) 現在 CRM を使用している AD ユーザー アカウントによって使用される AD 資格情報を資格情報オブジェクトに渡したい..
このアプリは Dynamics CRM 2011 の内部からのみ使用されることを意図していますが、理論的には、テスト目的でプラットフォームの外部でも動作する必要があります。
編集:スタックトレースを忘れたことに気づきました:
System.ServiceModel.FaultException: The request for security token could not be satisfied because authentication failed.
at System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target)
at System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState)The caller was not authenticated by the service.
Server stack trace:
at System.ServiceModel.Security.IssuanceTokenProviderBase`1.DoNegotiation(TimeSpan timeout)
at System.ServiceModel.Security.SspiNegotiationTokenProvider.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Security.CommunicationObjectSecurityTokenProvider.Open(TimeSpan timeout)
at System.ServiceModel.Security.SecurityProtocol.OnOpen(TimeSpan timeout)
at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.SecurityChannelFactory`1.ClientSecurityChannel`1.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout)
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOpenOnce.System.ServiceModel.Channels.ServiceChannel.ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)