سؤال

I have a self-hosted WCF service that is hosted by a desktop application.
I can successfully connect to the service locally on my PC, but I can't use the service remotely, at least without providing my windows/domain level credentials.

I use the following code to start the service in the app:

ServiceHost host = new ServiceHost(
            typeof (SMService),
            new Uri("net.tcp://localhost:" + SMGlobals._DEFAULTSERVICEPORT.ToString() + "/SMService"));

        host.AddServiceEndpoint(
            typeof(ISMService),
            new NetTcpBinding(),
            "");
        System.ServiceModel.Channels.Binding mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();

        var metadataBehavior =
            new ServiceMetadataBehavior();
        host.Description.Behaviors.Add(metadataBehavior);

        host.AddServiceEndpoint(
            typeof(IMetadataExchange),
            mexBinding,
            "net.tcp://localhost:" + SMGlobals._DEFAULTSERVICEPORT.ToString() + "/SMService/mex");

        host.Open();

        SMGlobals.SMServiceHost = host;

If I create a simple client to call the service using the following code:

var client = new SMServiceClient();
        var uri = "net.tcp://192.168.11.10:8760/SMService";
        client.Endpoint.Address = new EndpointAddress(uri);


        var initiateResponse = client.InitiateAuthentication(new InitiateAuthenticationRequest());

        MessageBox.Show("Success!");

I receive the following exception:

System.ServiceModel.Security.SecurityNegotiationException: The server has rejected the client credentials. ---> System.Security.Authentication.InvalidCredentialException: The server has rejected the client credentials. ---> System.ComponentModel.Win32Exception: The logon attempt failed

Now, from other research, I have discovered that I could provide my credentials with the client call using the following code:

var client = new SMServiceClient();
        var uri = "net.tcp://192.168.11.10:8760/SMService";
        client.Endpoint.Address = new EndpointAddress(uri);

        client.ClientCredentials.Windows.ClientCredential.Domain = "domain";
        client.ClientCredentials.Windows.ClientCredential.UserName = "my_user_name";
        client.ClientCredentials.Windows.ClientCredential.Password = "my_password";

        var initiateResponse = client.InitiateAuthentication(new InitiateAuthenticationRequest());

        MessageBox.Show("Success!");

And now, the code successfully completes.

I'm having a hard time figuring out how to remove this requirement. I've tried messing around with the binding setup on the client without success.

Can anyone point me in the right direction?

هل كانت مفيدة؟

المحلول

A Tcp Binding has security enabled by default, so to get what you want, you need to explicitly turn it off. Add your endpoint like this. You might also explore the MSDN help for NetTcpBinding as you might want to user an alternate constructor to also switch off reliable messaging.

 host.AddServiceEndpoint(
            typeof(ISMService),
            new NetTcpBinding(SecurityMode.None),
            "");

نصائح أخرى

Set the appropriate Authentication on the Binding.

ClientAuthenticationType="None"

I had a similar issue. Worked locally between two processes but the same code failed when the two processes were put on different machines (or locally using a public URL that resolved to the local machine, e.g. mylocalmachine.corp.com). I found that I needed to explicitly set the Anonymous binding's security to 'None':

<binding name="TcpAnonymousBinding" portSharingEnabled="true" receiveTimeout="24:00:00">
    <security mode="None"/>
</binding>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top