Intranet - web to remote wcf CredentialCache.DefaultNetworkCredentials not working

别说谁变了你拦得住时间么 提交于 2019-12-08 02:25:36

问题


I have a ASP.NET MVC intranet application hosted in IIS that added WCF service reference the WCF resides in another computer and also expect windows authentication. In my web this code is working great:

proxy = new MyProxyClient("configurationName", "remoteAddress");
proxy.ClientCredentials.Windows.ClientCredential.UserName = "myUserName";
proxy.ClientCredentials.Windows.ClientCredential.Password = "MyPassword";

proxy.SomeMethod(); //work great

but if I want the credential not to be hardcoded like this I am using: CredentialCache.DefaultNetworkCredentials like this:

 proxy = new MyProxyClient("configurationName", "remoteAddress");
 proxy.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;

 proxy.SomeMethod(); //not working throw exception

the above code throw SecurityNegotiationException with message: The caller was not authenticated by the service. and the inner exception is: The request for security token could not be satisfied because authentication failed.

How can I pass the credential of the current user to the WCF service without hardcoded user name and password?


回答1:


If your organization uses regular Windows authentication (NTLM) you can't do what you want due to "one-hop" restriction: credentials passed from user's computer to your server use "one-hop" (from direct login to one external computer) and such credentials can't be used to authenticate other servers from the first one.

More information can be found using following search term:ntlm one hop,i.e. Why NTLM fails and Kerberos works.

Standard solution:

  • Kerberos (often requires significant effort to get approval to enable/configure)
  • Use some other form of authentication than Windows. Consider if OAuth is possible. Don't go basic auth.
  • Switch WCF service to claims based authentication.
  • If WCF service can it can trust caller to verify incoming credentials more approaches are possible:
    1. Run code under particular account that signs in locally on server and have permissions to call the service. The easiest approach is what shown in your post, but storing domain passwords (or any passwords) in plain text is not secure. One can also run process account under special credentials that have access to the remote service and temporary revert impersonation after verifying user credentials.
    2. You can also configure WCF service to require client certificate and use such certificate when calling the WCF service. This way WCF service can verify if caller is known.



回答2:


In the web.config (client and server), in the <system.serviceModel> section add/modify a binding to look something like this:

<basicHttpBinding>
    <binding name="MyBasicBinding">
      <security mode="TransportCredentialOnly">
        <transport clientCredentialType="Windows" />
      </security>
    </binding>
</basicHttpBinding>

And, add this to client side web.config <system.web> section:

<identity impersonate="true" />
<authentication mode="Windows" />

The two changes will make the end-user the current user of the web request which will then be sent in the WCF message.

The user can then be retrieved on the server side like this:

ServiceSecurityContext.Current.WindowsIdentity

Please make sure the following configuration is there in service web.config.

<system.serviceModel> <services> <service name="MyWcf.Service1" behaviorConfiguration="MySvcBehavior"> <endpoint address="" binding="wsHttpBinding" contract="MyWcf.IService1" bindingConfiguration="MyWsHttpBinding"></endpoint> </service> </services> <bindings> <wsHttpBinding> <binding name="MyWsHttpBinding"> <security mode="Message"> <transport clientCredentialType="Windows"/> </security> </binding> </wsHttpBinding> <basicHttpBinding> <binding name="MyBasicBinding"> <security mode="Message"> <transport clientCredentialType="Windows" /> </security> </binding> </basicHttpBinding> </bindings> <behaviors> <serviceBehaviors> <behavior name="MySvcBehavior"> <!-- To avoid disclosing metadata information, set the values below to false before deployment --> <serviceMetadata httpGetEnabled="true"/> <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel>

And in your client configuration file following should be there.

<system.serviceModel> <bindings> <wsHttpBinding> <binding name="WSHttpBinding_IService1"> <security> <transport clientCredentialType="Windows" /> <message clientCredentialType="Windows" /> </security> </binding> </wsHttpBinding> </bindings> <client> <endpoint address="http://localhost/MyWcf/Service1.svc" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1" contract="MyWCFService.IService1" name="WSHttpBinding_IService1"> </endpoint> </client> </system.serviceModel>

I tried by passing System.Net.CredentialCache.DefaultNetworkCredentials using above configuration and working fine for me. If it's not working for you then put debug point on line which passing credential and watch that System.Net.CredentialCache.DefaultNetworkCredentials Domain, UserName & Password values are blank or not. If Blank then it should work.




回答3:


I assume that if you're looking within your CredentialCache.DefaultNetworkCredentials attribut you won't see the credential information. From Microsoft website : The authentication informations return by the DefaultNetworkCredentials property will be only available for NTLM, Negotiate or Kerberos authentication.

To get your credential you need to implement this authentication.

You can use it by using impersonation wihtin your intranet application. Impersonation allow your intranet application to be executed by the user of this one.

More information here :http://technet.microsoft.com/en-us/library/cc961980.aspx



来源:https://stackoverflow.com/questions/25010204/intranet-web-to-remote-wcf-credentialcache-defaultnetworkcredentials-not-worki

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!