WCF duplex service using net tcp: “Stream Security

2019-02-18 12:06发布

I'm writing a service that allows users to register with it and receive notifications when an event happens. I'm trying to do this with netTcpBinding, but keep coming up with errors, even when running on my local machine.

When I try to send a notification, I am timing out, getting this error:

Stream Security is required at http://www.w3.org/2005/08/addressing/anonymous, but no security context was negotiated. This is likely caused by the remote endpoint missing a StreamSecurityBindingElement from its binding.

For testing I am hosting the service in a console, and it is opening for me and I can see the WSDL and run svcutil on it. When I run the client though, and try to send a notification is when the error above shows up.

Host App.config:

<system.serviceModel>
<services>
  <service name="CompanyName.WebServices.InterventionService.RegistrationService"
           behaviorConfiguration="RegistrationServiceBehavior">
    <endpoint address="http://localhost:8000/CompanyName/Registration"
              binding="wsDualHttpBinding"
              contract="CompanyName.WebServices.InterventionService.Interfaces.IRegistrationService"/>
    <endpoint address="net.tcp://localhost:8001/CompanyName/Registration"
              binding="netTcpBinding"
              contract="CompanyName.WebServices.InterventionService.Interfaces.IRegistrationService"/>
  </service>
  <service name="CompanyName.WebServices.InterventionService.NotificationService"
           behaviorConfiguration="NotificationServiceBehavior">
    <endpoint address="http://localhost:8010/CompanyName/Notification"
              binding="wsDualHttpBinding"
              contract="CompanyName.WebServices.InterventionService.Interfaces.INotificationService"/>
    <endpoint address="net.tcp://localhost:8011/CompanyName/Notification"
              binding="netTcpBinding"
              contract="CompanyName.WebServices.InterventionService.Interfaces.INotificationService"/>
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="RegistrationServiceBehavior">
      <serviceMetadata httpGetEnabled="true"
                       httpGetUrl="http://localhost:8000/CompanyName/Registration"/>
    </behavior>
    <behavior name="NotificationServiceBehavior">
      <serviceMetadata httpGetEnabled="true"
                       httpGetUrl="http://localhost:8010/CompanyName/Notification"/>
    </behavior>
    <behavior name="netTcpRegistrationServiceBehavior">
      <serviceMetadata httpGetEnabled="true"
                       httpGetUrl="net.tcp://localhost:8001/CompanyName/Registration"/>
    </behavior>
    <behavior name="netTcpNotificationServiceBehavior">
      <serviceMetadata httpGetEnabled="true"
                       httpGetUrl="net.tcp://localhost:8011/CompanyName/Notification"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

Here is the client App.config:

<system.serviceModel>
<bindings>
  <netTcpBinding>
    <binding name="NetTcpBinding_IRegistrationService">
      <security mode="None">
        <message clientCredentialType="None"/>
        <transport clientCredentialType="None"/>
      </security>
    </binding>
    <binding name="NetTcpBinding_INotificationService">
      <security mode="None">
        <message clientCredentialType="None"/>
        <transport clientCredentialType="None"/>
      </security>
    </binding>
  </netTcpBinding>
  <wsDualHttpBinding>
    <binding name="WSDualHttpBinding_IRegistrationService">
      <reliableSession ordered="true"/>
      <security mode="None">
        <message clientCredentialType="None" negotiateServiceCredential="false"/>
      </security>
    </binding>
    <binding name="WSDualHttpBinding_INotificationService">
      <reliableSession ordered="true"/>
      <security mode="None">
        <message clientCredentialType="None" negotiateServiceCredential="false"/>
      </security>
    </binding>
  </wsDualHttpBinding>
</bindings>
<client>
  <endpoint address="http://localhost:8000/GPS/Registration"
            binding="wsDualHttpBinding"
            bindingConfiguration="WSDualHttpBinding_IRegistrationService"
            contract="IRegistrationService"
            name="WSDualHttpBinding_IRegistrationService">
  </endpoint>
  <endpoint address="net.tcp://localhost:8001/GPS/Registration"
            binding="netTcpBinding"
            bindingConfiguration="NetTcpBinding_IRegistrationService"
            contract="IRegistrationService"
            name="NetTcpBinding_IRegistrationService">
  </endpoint>
  <endpoint address="http://localhost:8010/GPS/Notification"
            binding="wsDualHttpBinding"
            bindingConfiguration="WSDualHttpBinding_INotificationService"
            contract="INotificationService"
            name="WSDualHttpBinding_INotificationService">
  </endpoint>
  <endpoint address="net.tcp://localhost:8011/GPS/Notification"
            binding="netTcpBinding"
            bindingConfiguration="NetTcpBinding_INotificationService"
            contract="INotificationService"
            name="NetTcpBinding_INotificationService">
  </endpoint>
</client>

I've omitted a lot of the registration code since I am only trying to get the notification working right now.

The plan is to host this in a windows service in 2003 Server that is not part of the customer's domain (their setup), and the client computers will be on the customer's domain.

Edit:

I have added the bindings to the host's App.config:

<bindings>
  <netTcpBinding>
    <binding name="NetTcpBinding_IRegistrationService">
      <security mode="None">
        <message clientCredentialType="None"/>
        <transport clientCredentialType="None"/>
      </security>
    </binding>
    <binding name="NetTcpBinding_INotificationService">
      <security mode="None">
        <message clientCredentialType="None"/>
        <transport clientCredentialType="None"/>
      </security>
    </binding>
  </netTcpBinding>
  <wsDualHttpBinding>
    <binding name="WSDualHttpBinding_IRegistrationService">
      <reliableSession ordered="true"/>
      <security mode="None">
        <message clientCredentialType="None" negotiateServiceCredential="false"/>
      </security>
    </binding>
    <binding name="WSDualHttpBinding_INotificationService">
      <reliableSession ordered="true"/>
      <security mode="None">
        <message clientCredentialType="None" negotiateServiceCredential="false"/>
      </security>
    </binding>
  </wsDualHttpBinding>
</bindings>

This still errors, with the same Steam Security is required error message. Trying a small subset of this app in a new solution.

2条回答
家丑人穷心不美
2楼-- · 2019-02-18 12:09

I think it turns out this is one of those horrible error messages that leads you into many different directions. The above answers is correct for that case. My case was different - my security settings were identical on client and serve.

In my case, this link pointed out my particular flaw: http://www.netframeworkdevs.com/windows-communication-foundation-wcf/error-invoking-service-with-a-net-tcp-binding-123918.shtml.

My service-side app.config for the Endpoint had bindingName as the attribute to name the binding configuration ... instead of bindingConfiguration. I don't think there even is an attribute named bindingName on an endpoint.

So ... my take away is that this error means "there is a WCF configuration error" perhaps narrowed to the service-side configuration. Ugh.

查看更多
放我归山
3楼-- · 2019-02-18 12:29

Well, your problem appears to be this:

  • on the server side, you use a default netTCP binding with no parameters - you don't change anything on it. netTCP defaults to transport-level security with Windows credentials

  • on your client however, you explicitly turn OFF any security on the netTCP binding

So the two don't match and don't agree on what to do.

Either you need to turn OFF all security on BOTH ends - server AND client - or you need to just use the secure defaults (with Windows credentials).

Marc

查看更多
登录 后发表回答