views:

29

answers:

1

We currently support several WCF services running in a load balanced environment. In the past, we have used wsHttpBinding and set establishSecurityContext to false to allow the service to work properly with our load balancer.

An issue we have ran into is that the wsHttpBinding encrypts the return results by default and, apparently, cannot be turned off. This causes issues with the Riverbed compression appliance we have on our network - i.e. the encrypted data does not compress very well (or at all).

Now we're attempting to make use of the basicHttpBinding since it does not encrypt the data by default. We have two requirements:

  1. Work with the load balancer - this appears to be possibly by using setting the keepAliveEnabled to false. This requires the use of a custom binding. For example:

    <customBinding>  
      <binding name="NewBinding0">  
        <httpTransport authenticationScheme="Ntlm" **keepAliveEnabled="false"** />  
      </binding>  
    </customBinding>  
    
  2. Passes User Credentials - this appears to be possible by setting the security mode to TransportCredentialOnly. This is available with the basicHttpBinding. For example:

    <basicHttpBinding>  
      <binding name="NewBinding1">  
        <security **mode="TransportCredentialOnly"** />  
      </binding>  
    </basicHttpBinding>  
    

So now for my actual question :-)... How/Is it possible to combine the above two requirements into a single custom binding? What is the equivalent of #2 above for a custom binding? How can I get it to pass the user credentials?

Thanks!

A: 

It turns out I was able to do what I wanted with the custom binding using the following binding configuration:

<customBinding>
 <binding name="NewBinding0">
 <httpTransport authenticationScheme="Ntlm" keepAliveEnabled="false" />
 </binding>
</customBinding>

Then, on the client side, I could use the following code to get the identity of the application pool the WCF service was running under (in IIS) as well as the identity of the user who actually called the WCF service:

public string GetData(int value)
{
  var callingUser = string.Empty;
  var appPoolUser = WindowsIdentity.GetCurrent().Name;
  var identities =
    OperationContext.Current.ServiceSecurityContext.AuthorizationContext.Properties["Identities"] as
    IList<IIdentity>;

  if (identities != null)
  {
    var result = from i in identities
            where i.AuthenticationType == "NTLM"
            select new { i.Name };

    if (result.Count() > 0)
    {
      callingUser = result.First().Name;
    }

  }

  return string.Format("Value Entered: {0}; AppPool User: {1}; Calling User: {2}", value,
          appPoolUser, callingUser);
}

I tested the above code in a load balanced environment, for Requirement #1, and everything seemed to run just fine. The tests simulated a 100-user load for 10 minutes in a load balanced environment. We took one of the load balanced servers down during the test and everything continued to run as expected (i.e. no exceptions were thrown during the tests nor did any identities come back incorrectly).

The code above is the key piece, for Requirement #2, that I was missing - i.e. I didn't realize until this research that WCF would give you multiple identities.

Also, using this configuration, the results of the WCF call is not encrypted (which is what we wanted). So, I think this configuration will work for our situation just fine.

Jeff Bramwell