ASP.NET website -> WCF service -> WCF service, with impersonation all the way?
In short my scenario is like so:
- The user triggers an action in the web browser, which causes an Ajax call to a web service in the web server (server A).
- The web server issues a call to a WCF service, hosted in IIS (server B)
- The WCF service issues a call to another WCF service, hosted in IIS (server C)
All web sites are exposed over http, not https.
Now, server C needs to know who the user is in the other end. I got it working so far so that the WCF service call to server B is performed under impersonation, so server B has a WindowsIdentity
object representing the user. However, when I try to invoke the service call from server B to server C under impersonation, I get the following back:
System.ComponentModel.Win32Exception: No credentials are available in the security package
Server stack trace:
at System.IdentityModel.SspiWrapper.AcquireCredentialsHandle(String package, Credenti开发者_开发技巧alUse intent, AuthIdentityEx& authdata)
at System.ServiceModel.Security.SecurityUtils.GetCredentialsHandle(String package, NetworkCredential credential, Boolean isServer, String[] additionalPackages)
at System.ServiceModel.Security.SpnegoTokenProvider.OnOpening()
at System.ServiceModel.Security.WrapperSecurityCommunicationObject.OnOpening()
at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout)
at System.ServiceModel.Security.CommunicationObjectSecurityTokenProvider.Open(TimeSpan timeout)
at System.ServiceModel.Security.SecurityUtils.OpenTokenProviderIfRequired(SecurityTokenProvider tokenProvider, TimeSpan timeout)
at System.ServiceModel.Security.SymmetricSecurityProtocol.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.EnsureOpened(TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Tweaking service binding feels for me like walking on ice so thin that I am almost walking on water, so let's disregard from what I have failed with so far, and start with a clean sheet.
How should I configure the services to play nicely with each other (and me)?
According to Microsoft, you need to use something called "Delegation", which if I understand correctly, is specifying that Server C trusts Server B to properly authenticate the user from Server A.
Without Delegation, your service on Server B can only access local resources as the impersonated user from Server A.
From the horse's mouth: http://msdn.microsoft.com/en-us/library/cc949014.aspx
Because you are making more than one hop, you need to use delegation. Take a look here for more information.
精彩评论