简体   繁体   中英

WCF / wsHttpBinding / Message Security - BadTokenRequest

So got an older WCF service / client I'm working on. Added a new (static) logging system to it, actually and now doing some load testing.

Getting some really annoying sporadic issues now - claiming "Secure channel cannot be opened because security negotiation with the remote endpoint has failed". I noticed I get a CommunicationException with a fault name of Sender and subcode of BadContextToken.

Weird thing is, I'll get 2-4 correct responses, then a flurry of these exceptions, then start getting good responses again.

This is my first real foray into WCF, and not loving it so far :)

Service web.config:

<system.serviceModel>
  <bindings>
    <wsHttpBinding>
      <security mode="Message">
        <message clientCredentialType="UserName" />
      </security>
    </wsHttpBinding>
  </bindings>
  <services>
    <service behaviorConfiguration="ServiceBehavior" name="MyNamespace.MyService">
      <endpoint address="" binding="wsHttpBinding" contract="MyNamespace.IMyService" bindingConfiguration="wsMessage">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </service>
  </services>
  <behaviors>
    <serviceBehaviors>
      <behavior name="ServiceBehavior">
        <serviceMetadata httpGetEnabled="false" />
        <serviceCredentials>
          <serviceCertificate findValue="MyValue" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
          <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyNamespace.UserNamePassValidator, MyNamespace" />
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

And on the client side, the client is instantiated as such:

var binding = new WSHttpBinding();
binding.Name = "WSHttpBinding_IMyService";
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName;

var client = new MyService(binding, "http://myserver:8080/myapp/service.svc");

var endpointIdentity = new DnsEndpointIdentity("MyValue"); // Match the certificate name used by the server

client.Endpoint.Address = new EndpointAddress(new Uri("http://myserver:8080/myapp/service.svc"), endpointIdentity, client.Endpoint.Address.Headers);

var creds = client.ClientCredentials;

creds.ServiceCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.None;
creds.UserName.UserName = "myuser";
creds.UserName.Password = "mypassword";

string retVal = client.SendRequest(); // SendRequest == one of the methods on my IMyService, returns a string.  This is also where I sporadically see my error when load testing.

I would appreciate any pointers to help me out with this WCF setup!

These might be useful additions to your web.config:

<behaviors> 
    <serviceBehaviors> 
        <behavior name="CalculatorServiceBehavior">
            <serviceDebug includeExceptionDetailInFaults="False" /> 
            <serviceMetadata httpGetEnabled="True"/> 
            <serviceThrottling maxConcurrentCalls="20" maxConcurrentInstances="100"/> 
        </behavior>
     </serviceBehaviors>
</behaviors>

<binding name="basicHttp" allowCookies="true" maxReceivedMessageSize="1048576" maxBufferSize="1048576" maxBufferPoolSize="1048576">
    <readerQuotas maxDepth="32" maxArrayLength="1048576" maxStringContentLength="1048576"/>
</binding>

Usually this kind of "random" behaviour might depend on:

  1. Timeouts (probably not your case, since you'd get a different exception)
  2. Too many connections: if you client opens too many connections (and "forgets" to close them), you'll exceed the default allowed maximum (depending on context, it might be 10 connections). You can act on this if you alter your web.config, editing maxConcurrentCalls and maxConcurrentInstances
  3. Perhaps those errors are not random, but specific to some message; if so, that might be due to its size (ie it's too large): again, alter your web.config setting maxReceivedMessageSize , maxBufferSize , maxBufferPoolSize and readerQuotas

Of course you will get more info if you turn on WCF tracing .

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