WCF: Using binary encoding with security

Posts   
 
    
Nightowl33
User
Posts: 8
Joined: 31-Mar-2009
# Posted on: 31-Mar-2009 04:38:17   

Hello! I've just downloaded the trial of llblgen and am working with the (very helpful) WCF example I downloaded. (DISCLAIMER: I'm clearly not a WCF expert, so be gentle.)

Here's my dilemma. I'm trying to add security (based on the ASP.NET membership provider) to that tutorial, and it works when I use this binding (and set up X509 certificates, etc etc.):

      <wsHttpBinding>
        <binding name="testWsBinding">
          <security mode="Message">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>

But as I'm gathering from other threads, my best performance would come from using binaryMessageEncoding, so i'm trying to get a combination of that with security, and it's all kinds of cranky about it. If I use:

    <customBinding>
        <binding name="NetHttpBinding">
          <reliableSession />
           <security authenticationMode="UserNameForCertificate">
          </security>
         <compositeDuplex />
          <oneWay />
          <binaryMessageEncoding />
          <httpTransport />
        </binding>
   </customBinding>

then I get errors about it not liking the order of the parameters, which since the parameters are IN the order it suggests, I assume it's really code for 'you're trying to do something you shouldn't, you idiot.' On the other hand, if I just do:

        <binding name="SecureNetHttpBinding">
          <security authenticationMode="UserNameForCertificate">
          </security>
          <binaryMessageEncoding />
          <httpTransport />
        </binding>

then I get errors about not finding the certificate in the client settings(even though it works just fine with the wsHttpBinding version). Plus, I don't know if leaving out those other parameters is going to have an impact on me/my application.

I realize this is much more a WCF question than a llblgen question, but I really do need the combination of WCF, security, AND not-totally-terrible performance.

.NET 3.5 SP1, Visual Studio 2008 SP1, (and llblgen 2.6 final demo, with the WCF example downloaded yesterday)

Help? Is there a best practice here?

Thanks in advance, Scott

For the brave - here's the whole servicemodel section of my web.config:

<system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceTypeBehaviors" >
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true"/>
          <serviceCredentials>
            <serviceCertificate findValue="CN=localhost"/>
            <userNameAuthentication userNamePasswordValidationMode="MembershipProvider"
                    membershipProviderName="TASDashboardMembershipProvider" />
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <customBinding>
        <binding name="NetHttpBinding">
          <reliableSession />
          <compositeDuplex />
          <oneWay />
          <binaryMessageEncoding />
          <httpTransport />
        </binding>
        <binding name="SecureNetHttpBinding">
          <security authenticationMode="UserNameForCertificate">
          </security>
          <binaryMessageEncoding />
          <httpTransport />
        </binding>
      </customBinding>
      <wsHttpBinding>
        <binding name="testWsBinding">
          <security mode="Message">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <services>
      <service name="SD.LLBLGen.Pro.Examples.WCF.Service.NorthwindService" behaviorConfiguration="MyServiceTypeBehaviors">
        <endpoint address=""
                  binding="customBinding"
                  bindingConfiguration="SecureNetHttpBinding"
                  contract="SD.LLBLGen.Pro.Examples.WCF.ServiceInterface.INorthwindService">
          <identity>
            <certificateReference storeName="My" storeLocation="LocalMachine" findValue="CN=localhost"/>
          </identity>
        </endpoint>

        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>

and the whole app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <customBinding>
        <binding name="NetHttpBinding">
          <reliableSession />
          <compositeDuplex />
          <oneWay />
          <binaryMessageEncoding />
          <httpTransport />
        </binding>
        <binding name="SecureNetHttpBinding">
          <security authenticationMode="UserNameForCertificate">
          </security>
          <binaryMessageEncoding />
          <httpTransport />
        </binding>
      </customBinding>
      <wsHttpBinding>
        <binding name="testWsBinding">
          <security mode="Message">
            <message clientCredentialType="UserName"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <!-- remove behaviorConfiguration on next line for production -->
      <endpoint address="http://localhost/WCFService/CustomerService.svc"
                 behaviorConfiguration = "ServiceCertificate"
                name="WCFServer"
                binding="customBinding"
                bindingConfiguration="SecureNetHttpBinding"
                contract="SD.LLBLGen.Pro.Examples.WCF.ServiceInterface.INorthwindService">
        <!-- remove this identity section for production -->
        <identity>
          <dns value="localhost"/>
        </identity>
      </endpoint>
    </client>
    <behaviors>
      <endpointBehaviors>
        <behavior name = "ServiceCertificate">
          <clientCredentials>
            <serviceCertificate>
              <authentication certificateValidationMode = "PeerTrust"/>
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>
Nightowl33
User
Posts: 8
Joined: 31-Mar-2009
# Posted on: 31-Mar-2009 07:34:42   

Well, I think I've gotten farther, but I'm certainly open to a WCF expert to tell me what I could do better.

Courtesy of http://blog.salamandersoft.co.uk/CommentView,guid,0b691f56-47eb-4715-8ffd-134250a70817.aspx I was able to translate the wsHttpBinding into a customBinding, and then add the various extra parameters, including binaryMessageEncoding. So my custom binding now looks like:

        <binding name="SecureNetHttpBinding">
          <transactionFlow transactionProtocol="WSAtomicTransactionOctober2004" />
          <reliableSession />
          <security defaultAlgorithmSuite="Default" authenticationMode="SecureConversation"
                    requireDerivedKeys="true" securityHeaderLayout="Strict" includeTimestamp="true"
                    keyEntropyMode="CombinedEntropy" messageProtectionOrder="SignBeforeEncryptAndEncryptSignature"
                    messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
                    requireSecurityContextCancellation="true" requireSignatureConfirmation="false">
            <localClientSettings cacheCookies="true" detectReplays="true"
                                 replayCacheSize="900000" maxClockSkew="00:05:00" maxCookieCachingTime="Infinite"
                                 replayWindow="00:05:00" sessionKeyRenewalInterval="10:00:00"
                                 sessionKeyRolloverInterval="00:05:00" reconnectTransportOnFailure="false"
                                 timestampValidityDuration="00:05:00" cookieRenewalThresholdPercentage="60" />
            <localServiceSettings detectReplays="true" issuedCookieLifetime="10:00:00"
                                  maxStatefulNegotiations="128" replayCacheSize="900000" maxClockSkew="00:05:00"
                                  negotiationTimeout="00:01:00" replayWindow="00:05:00" inactivityTimeout="00:02:00"
                                  sessionKeyRenewalInterval="15:00:00" sessionKeyRolloverInterval="00:05:00"
                                  reconnectTransportOnFailure="false" maxPendingSessions="128"
                                  maxCachedCookies="1000" timestampValidityDuration="00:05:00" />
            <secureConversationBootstrap defaultAlgorithmSuite="Default"
                                         authenticationMode="UserNameForSslNegotiated" requireDerivedKeys="true"
                                         securityHeaderLayout="Strict" includeTimestamp="true" keyEntropyMode="CombinedEntropy"
                                         messageProtectionOrder="SignBeforeEncryptAndEncryptSignature"
                                         messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
                                         requireSecurityContextCancellation="true" requireSignatureConfirmation="false">
              <localClientSettings cacheCookies="true" detectReplays="true"
                                   replayCacheSize="900000" maxClockSkew="00:05:00" maxCookieCachingTime="Infinite"
                                   replayWindow="00:05:00" sessionKeyRenewalInterval="10:00:00"
                                   sessionKeyRolloverInterval="00:05:00" reconnectTransportOnFailure="true"
                                   timestampValidityDuration="00:05:00" cookieRenewalThresholdPercentage="60" />
              <localServiceSettings detectReplays="true" issuedCookieLifetime="00:15:00"
                                    maxStatefulNegotiations="128" replayCacheSize="900000" maxClockSkew="00:05:00"
                                    negotiationTimeout="00:01:00" replayWindow="00:05:00" inactivityTimeout="00:02:00"
                                    sessionKeyRenewalInterval="15:00:00" sessionKeyRolloverInterval="00:05:00"
                                    reconnectTransportOnFailure="true" maxPendingSessions="128"
                                    maxCachedCookies="1000" timestampValidityDuration="00:05:00" />
            </secureConversationBootstrap>
          </security>
          <compositeDuplex />
          <oneWay />
          <binaryMessageEncoding />
          <httpTransport />
        </binding>

I'm guessing I don't need all that detail but it does seem to work. Time to sleep. Again, totally open to input on doing this better... simple_smile