Perfil de ZulfiqarZulfiqar's SpaceBlogListasSkyDrive Herramientas Ayuda

Blog


    08/10/2007

    How to set ProtectionLevel from config

    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 the 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.
    [ServiceContract(Namespace = "http://www.zamd.net/Calcualtor", ProtectionLevel = ProtectionLevel.Sign)] public interface ICalculator { [OperationContract] int Add(int a, int b); }

    all good so far, however there are couple of limitation with the current implementation.

    1. ProtectionLevel can only be set in the code. Its quite common requirement that operations/IT want to control the protection level as part of the deployment. Hard coding protection level in code as an attribute is quite in-efficient in that case. As you have to recompile to change the protection level.
    2. Another more subtle requirement I have seen is to have the ability to have different Protectionlevel for different endpoints sharing the same contract.  e.g  an intranet endpoint and an internet endpoint sharing the same contract. You might want to only sign the messages for intranet communication while both singing and encrypting for internet communication. Currently because Protectionlevel is specified as part of the contract, which gets shared by multiple endpoints. There is no built-in way to achieve this other than creating multiple contracts.

    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 object.

    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 access ChannelProtectionRequirements parameter to specify endpoint specific protection requirements for that endpoint. 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>

    Complete Source

    enjoy :)

    Comentarios

    Espera...
    El comentario que has escrito es demasiado largo. Acórtalo.
    No has escrito nada. Vuelve a intentarlo.
    No se puede agregar tu comentario en este momento. Vuelve a intentarlo más tarde.
    Para agregar un comentario, necesitas permiso de tus padres. Pedir permiso
    Tus padres han desactivado los comentarios.
    No se puede eliminar tu comentario en este momento. Vuelve a intentarlo más tarde.
    Has superado el número máximo de comentarios que se puede dejar en un día. Vuelve a intentarlo en 24 horas.
    Se ha deshabilitado la capacidad de tu cuenta de dejar comentarios porque nuestros sistemas indican que podrías estar enviando correo no solicitado a otros usuarios. Si crees que tu cuenta se ha deshabilitado por error, ponte en contacto con el servicio de soporte técnico de Windows Live.
    Para terminar de dejar tu comentario, realiza la siguiente comprobación de seguridad.
    Los caracteres que escribas en la comprobación de seguridad deben coincidir con los de la imagen o el audio.

    Para agregar un comentario, inicia sesión con tu cuenta de Windows Live ID (si utilizas Hotmail, Messenger o Xbox LIVE, ya tienes una cuenta de Windows Live ID). Iniciar sesión


    ¿No tienes una cuenta de Windows Live ID? Regístrate

    Vínculos de referencia

    La dirección URL del vínculo de referencia de esta entrada es:
    http://ahmed0192.spaces.live.com/blog/cns!FD6F44C91F5D2AD9!152.trak
    Weblogs que hacen referencia a esta entrada
    • Ninguno