Protectionlevel enum defines the level of security in terms of encryption & signature. When programing at the Service Model layer, ProtectionLevel can be set at various levels:

·         ServiceContract level: all messages/faults of a service contract will have same protection level

·         OperationContract level: An operation can override the protection level specified at the contract level. So messages/faults of an operation can have different protection requirements.

·         MessageContract level: Individual messages/faults can also specify their own protection level, overriding the one specified at higher level.

If your only requirement is to be able to set protection level from config file, then a simple option could be to access the description object model and update the contract protection level there before opening the service host or proxy.

ServiceHost svc = new ServiceHost(typeof(CalculatorService));

svc.Description.Endpoints[0].Contract.ProtectionLevel = GetProtectionLevelFromConfig();

If however, you want to set different protection level for different endpoints, then you have to do some more work.

Specifically you have to create an endpoint behavior, from which you will access the ChannelProtectionRequirements parameter to specify endpoint specific protection requirements. Here is step by step procedure to do this:

1.       Create an endpoint behavior and add following code to AddBindingParameters method.

    public class ProtectionLevelBehavior : IEndpointBehavior

    {

        ProtectionLevel level;

 

        internal ProtectionLevelBehavior(ProtectionLevel level)

        {

            this.level = level;

        }

        #region IEndpointBehavior Members

 

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)

        {

            var proReq =

                bindingParameters.Remove<ChannelProtectionRequirements>();

            proReq = new ChannelProtectionRequirements();

            MessagePartSpecification unProtectedSpec = new MessagePartSpecification();

            MessagePartSpecification protectedSpec = new MessagePartSpecification(true);

            //I'm setting same protection level for all the actions.

            // You could specify different protection level per action, if required.

            // Also note, I haven't implemented any support for custom SOAP headers.

            // However that can easily be added using the same mechansim.

            switch (level)

            {

                case ProtectionLevel.None:

                    proReq.OutgoingSignatureParts.AddParts(unProtectedSpec, "*");

                    proReq.IncomingSignatureParts.AddParts(unProtectedSpec, "*");

                    proReq.OutgoingEncryptionParts.AddParts(unProtectedSpec, "*");

                    proReq.IncomingEncryptionParts.AddParts(unProtectedSpec, "*");

                    break;

                case ProtectionLevel.Sign:

                    proReq.OutgoingSignatureParts.AddParts(protectedSpec, "*");

                    proReq.IncomingSignatureParts.AddParts(protectedSpec, "*");

                    proReq.OutgoingEncryptionParts.AddParts(unProtectedSpec, "*");

                    proReq.IncomingEncryptionParts.AddParts(unProtectedSpec, "*");

                    break;

                case ProtectionLevel.EncryptAndSign:

                    proReq.OutgoingSignatureParts.AddParts(protectedSpec, "*");

                    proReq.IncomingSignatureParts.AddParts(protectedSpec, "*");

                    proReq.OutgoingEncryptionParts.AddParts(protectedSpec, "*");

                    proReq.IncomingEncryptionParts.AddParts(protectedSpec, "*");

                    break;

            }

            // Add our protection requirement for this endpoint into the binding params.

            bindingParameters.Add(proReq);

        }

        public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)

        {

        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)

        {

        }

        public void Validate(ServiceEndpoint endpoint)

        {

        }

        #endregion

    }

2.       Now create a behavior extension so that this behavior can be enabled/disabled using configuration file. The behavior extension will read the configured protectionLevel from config file and will create an instance of above endpoint behavior to plug it into behavior collections.

    //behavior configuration extension element

        public class ProtectionLevelBehaviorElement : BehaviorExtensionElement

        {

            public ProtectionLevelBehaviorElement()

            {

            }

            public override Type BehaviorType

            {

                get { return typeof(ProtectionLevelBehavior); }

            }

 

            protected override object CreateBehavior()

            {

                return new ProtectionLevelBehavior(this.Level);

            }

            [ConfigurationProperty("level")]

            public ProtectionLevel Level

            {

                get

                {

                    return (ProtectionLevel)base["level"];

                }

                set

                {

                    base["level"] = value;

                }

            }

            ConfigurationPropertyCollection properties = null;

            protected override ConfigurationPropertyCollection Properties

            {

                get

                {

                    if (this.properties == null)

                    {

                        ConfigurationPropertyCollection propertys = new ConfigurationPropertyCollection();

                        propertys.Add(new ConfigurationProperty("level", typeof(ProtectionLevel), null, ConfigurationPropertyOptions.IsRequired));

                        this.properties = propertys;

                    }

                    return this.properties;

                }

            }

        }

3.      And this is how you will specify the protection level from config file using the above behavior extension.

  <behaviors>

    <endpointBehaviors>

      <behavior name="endpointSecurityConfig">

        <protectionLevel level="Sign"/>

        <!-- None, Sign, EncryptAndSign-->

      </behavior>

    </endpointBehaviors>

  </behaviors>

I have attached the source code with this post. Feel free to download and reuse.

Download: protectionlevelsample.zip