简体   繁体   中英

.Net Core 2.0 call to WCF client configuration

I have a .NET Core 2.0 application and need to call a WCF client from one of its controllers, and pass the user credentials for authentication.

Within the .net core app I created a reference for the WCF client using the Connected Services (WCF Web Service Reference Provider) and now in a process of configuring the call. Note that I can use the same endpoint form a 4.6 framework application without any problems.

Here's my code:

        var binding = new BasicHttpBinding {Security = {Mode = BasicHttpSecurityMode.Transport}};

        var address = new EndpointAddress("https://my-endpoint.asmx");

        var client  = new MyAppSoapClient(binding, address);

        var credentials = CredentialCache.DefaultNetworkCredentials; 

        client.ClientCredentials.Windows.ClientCredential = credentials;
        client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;

        var response = client.GetStuff("param").Result;

I face a number of problems:

It has to be a https call
I need to pass the currently log in user credentials to the call

The current error I get is as follows:

The HTTP request is unauthorized with client authentication scheme 'Anonymous'. The authentication header received from the server was 'Negotiate, NTLM'

Also the ConnectedService.json (created automativcally by WCF Web Service Reference Provider) has a predefined endpoint Uri.. I don't understand why I need to pass the address to the client manually (the code seems to be forcing me to do so).. ideally I'd like to get this dynamically amended in json depending on environment.

Thanks.

I noticed that you passed the current logged-in user as a Windows credential (which is also necessary for enabling impersonation), but you did not explicitly set the client credentials for the transport layer security.

BasicHttpBinding binding = new BasicHttpBinding();
            binding.Security.Mode = BasicHttpSecurityMode.Transport;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;

Also the ConnectedService.json (created automativcally by WCF Web Service Reference Provider) has a predefined endpoint Uri.. I don't understand why I need to pass the address to the client manually (the code seems to be forcing me to do so)

You can modify the method of automatic generation of proxy client to construct client proxy class (located in the reference.cs)
Modify the binding security

private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
        {
            if ((endpointConfiguration == EndpointConfiguration.WebService1Soap))
            {
                System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
                result.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.Transport;
                result.Security.Transport.ClientCredentialType = System.ServiceModel.HttpClientCredentialType.Windows;
                result.MaxBufferSize = int.MaxValue;
                result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
                result.MaxReceivedMessageSize = int.MaxValue;
                result.AllowCookies = true;
                return result;
            }

Modify the endpoint.

  private static System.ServiceModel.EndpointAddress GetEndpointAddress(EndpointConfiguration endpointConfiguration)
    {
        if ((endpointConfiguration == EndpointConfiguration.WebService1Soap))
        {
            return new System.ServiceModel.EndpointAddress("http://10.157.13.69:8001/webservice1.asmx");

Construct the client proxy class.

ServiceReference1.WebService1SoapClient client = new WebService1SoapClient(WebService1SoapClient.EndpointConfiguration.WebService1Soap);
            client.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
            client.ClientCredentials.Windows.ClientCredential.UserName = "administrator";
            client.ClientCredentials.Windows.ClientCredential.Password = "123456";

Feel free to let me know if there is anything I can help with.

My binding was missing the security Ntlm credential type (see below).

Problem solved.

    var binding = new BasicHttpBinding {Security = {Mode = BasicHttpSecurityMode.Transport,
        Transport = new HttpTransportSecurity(){ClientCredentialType = HttpClientCredentialType.Ntlm } }};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM