Showing posts with label WCF. Show all posts
Showing posts with label WCF. Show all posts

How to disable WCF authentication

Without explicit configuration a WCF service will always try to authenticate the caller. If you don't want this (and you want to avoid faults such as "the caller was not authenticated by the service" or "the request for security token could not be satisfied") you can simply disable WCF security by creating a custom binding with security mode to None. Here's how the system.serviceModel in the web.config should look like:

    <!-- Server Side -->
    <services>
      <service name="Service"
               behaviorConfiguration="ServiceBehavior">
        <endpoint address=""
                  binding="wsHttpBinding"
                  bindingConfiguration="UnsecuredBinding"
                  contract="IService" />
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange"/>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="UnsecuredBinding">
          <security mode="None">
            <message establishSecurityContext="false"/>
            <transport clientCredentialType="None"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>


Client applications should of course connect with a compatible binding. A standard wsHttp binding will assume security at Message level, so you will bump into a "secure channel cannot be opened because security negotiation with the remote endpoint has failed" fault. Here's how the system.serviceModel in the app.config should look like:

    <!-- Client Side -->
    <bindings>
      <wsHttpBinding>
        <binding name="UnsecuredBinding">
          <security mode="None">
            <message establishSecurityContext="false"/>
            <transport clientCredentialType="None"/>
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://www.dotbay.be/Service.svc"
                binding="wsHttpBinding"
                bindingConfiguration="UnsecuredBinding"
                contract="IService"
                name="UnsecuredBinding">
        <identity>
          <dns value="localhost" />
        </identity>
      </endpoint>
    </client>


By the way, the system.web settings are ignored, so no authentication takes place, even with this setting on the server side:
    <authentication mode="Windows"/>

Compressing a WCF Message

Every now and then there's a WCF message that passes the MaxReceivedMessageSize threshold. Here's a nice little helper class that will allow you to compress and decompress it, without depending on extra WCF configurations. For serialization it uses the XML-based DataContractSerializer, so you can deserialize the original types into other types and namespaces. For compression it uses a DeflateStream instead of a GZipStream for less overhead.

namespace DockOfTheBay
{
    using System.Diagnostics.CodeAnalysis;
    using System.IO;
    using System.IO.Compression;
    using System.Runtime.Serialization;
 
    public static class CompressedSerializer
    {
        [SuppressMessage("Microsoft.Design", "CA1004:GenericMethodsShouldProvideTypeParameter")]
        public static T Decompress<T>(byte[] compressedData)
        {
            using (MemoryStream memory = new MemoryStream(compressedData))
            {
                using (DeflateStream zip = new DeflateStream(memory, CompressionMode.Decompress, true))
                {
                    var formatter = new DataContractSerializer(typeof(T));
                    return (T)formatter.ReadObject(zip);
                }
            }
        }
 
        public static byte[] Compress<T>(T data)
        {
            using (MemoryStream memory = new MemoryStream())
            {
                using (DeflateStream zip = new DeflateStream(memory, CompressionMode.Compress, true))
                {
                    var formatter = new DataContractSerializer(typeof(T));
                    formatter.WriteObject(zip, data);
                }
 
                return memory.ToArray();
            }
        }
    }
}