Compartir a través de


Tutorial: Crear credenciales de cliente y servicio personalizadas

En este tema se muestra cómo implementar credenciales de cliente y servicio personalizadas y cómo utilizar las credenciales personalizadas desde el código de la aplicación.

Clases de extensibilidad de credenciales

Las clases ClientCredentials y ServiceCredentials son los puntos de entrada principales a la extensibilidad de la seguridad de Windows Communication Foundation (WCF). Estas clases de credenciales proporcionan las API que permiten al código de la aplicación establecer información de las credenciales y convertir los tipos de credenciales en tokens de seguridad. (Los tokens de seguridad son la forma que se usa para transmitir información de credenciales dentro de los mensajes SOAP). Las responsabilidades de estas clases de credenciales pueden dividirse en dos áreas:

  • Proporcione las API para que las aplicaciones establezcan la información de las credenciales.

  • Haga las funciones de un generador para las implementaciones de SecurityTokenManager.

Las implementaciones predeterminadas proporcionadas en WCF admiten los tipos de credenciales proporcionados por el sistema y crean un administrador de tokens de seguridad que es capaz de administrar esos tipos de credenciales.

Razones para personalizar

Hay varias razones para personalizar las clases de credenciales de cliente o servicio. En primer lugar está el requisito de cambiar el comportamiento de seguridad predeterminado de WCF con respecto a la administración de los tipos de credenciales proporcionados por el sistema, sobre todo por las razones siguientes:

  • Cambios que no son posibles mediante otros puntos de extensibilidad.

  • Agregar nuevos tipos de credenciales.

  • Agregar nuevos tipos de tokens de seguridad personalizados.

En este tema se describe cómo implementar credenciales de cliente y servicio personalizadas y cómo utilizarlas desde el código de la aplicación.

Primero en una serie

Crear una clase de credenciales personalizadas sólo es el primer paso, porque la razón para personalizar las credenciales es cambiar el comportamiento de WCF con respecto al suministro de credenciales, serialización de tokens de seguridad o autenticación. Otros temas en esta sección describen cómo crear serializadores y autenticadores personalizados. En este aspecto, crear la clase de credenciales personalizada es el primer tema de la serie. Las acciones subsiguientes (crear serializadores y autenticadores personalizados) sólo se pueden hacer después de crear las credenciales personalizadas. Entre los temas adicionales que se generan a partir de este tema se incluyen:

Procedimientos

Para implementar credenciales de cliente personalizadas

  1. Defina una clase nueva derivada de la clase ClientCredentials.

  2. Opcional. Agregue nuevos métodos o propiedades para los nuevos tipos de credenciales. Si no agrega nuevos tipos de credencial, no realice este paso. En el ejemplo siguiente se agrega una propiedad CreditCardNumber.

  3. Invalide el método CreateSecurityTokenManager . La infraestructura de seguridad de WCF llama automáticamente a este método cuando se usa la credencial de cliente personalizada. Este método es responsable de crear y devolver una instancia de una implementación de la clase SecurityTokenManager.

    Importante

    Es importante tener en cuenta que el método CreateSecurityTokenManager se invalida para crear un administrador de tokens de seguridad personalizado. El administrador de tokens de seguridad, derivado de ClientCredentialsSecurityTokenManager, debe devolver un proveedor de tokens de seguridad personalizado, derivado de SecurityTokenProvider, para crear el token de seguridad propiamente dicho. Si no sigue este patrón para crear los tokens de seguridad, la aplicación puede tener un funcionamiento incorrecto al almacenar los objetos ChannelFactory en la memoria caché (que es el comportamiento predeterminado para los servidores proxy de cliente de WCF), lo que puede producir un ataque de elevación de privilegios. El objeto de credencial personalizado se almacena en memoria caché como parte de la clase ChannelFactory. Sin embargo, la clase SecurityTokenManager personalizada se crea en cada invocación, lo que mitiga la amenaza de seguridad siempre que la lógica de creación de tokens se sitúe en la clase SecurityTokenManager.

  4. Invalide el método CloneCore .

    public class MyClientCredentials : ClientCredentials
    {
        string creditCardNumber;
    
        public MyClientCredentials()
        {
            // Perform client credentials initialization.
        }
    
        protected MyClientCredentials(MyClientCredentials other)
            : base(other)
        {
            // Clone fields defined in this class.
            this.creditCardNumber = other.creditCardNumber;
        }
    
        public string CreditCardNumber
        {
            get
            {
                return this.creditCardNumber;
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }
                this.creditCardNumber = value;
            }
        }
    
        public override SecurityTokenManager CreateSecurityTokenManager()
        {
            // Return your implementation of the SecurityTokenManager.
            return new MyClientCredentialsSecurityTokenManager(this);
        }
    
        protected override ClientCredentials CloneCore()
        {
            // Implement the cloning functionality.
            return new MyClientCredentials(this);
        }
    }
    
    Public Class MyClientCredentials
        Inherits ClientCredentials
        Private creditCardNumberValue As String
    
        Public Sub New()
    
        End Sub
    
        ' Perform client credentials initialization.    
        Protected Sub New(ByVal other As MyClientCredentials)
            MyBase.New(other)
            ' Clone fields defined in this class.
            Me.creditCardNumberValue = other.creditCardNumberValue
    
        End Sub
    
        Public Property CreditCardNumber() As String
            Get
                Return Me.creditCardNumberValue
            End Get
            Set
                If value Is Nothing Then
                    Throw New ArgumentNullException("value")
                End If
                Me.creditCardNumberValue = value
            End Set
        End Property
    
        Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager
            ' Return your implementation of the SecurityTokenManager.
            Return New MyClientCredentialsSecurityTokenManager(Me)
    
        End Function
    
        Protected Overrides Function CloneCore() As ClientCredentials
            ' Implement the cloning functionality.
            Return New MyClientCredentials(Me)
    
        End Function
    End Class
    

Para implementar un administrador de tokens de seguridad de cliente personalizados

  1. Defina una clase nueva derivada a partir de ClientCredentialsSecurityTokenManager.

  2. Opcional. Invalide el método CreateSecurityTokenProvider(SecurityTokenRequirement) si se debe crear una implementación de SecurityTokenProvider personalizada. Para más información sobre los proveedores de tokens de seguridad personalizados, consulte Procedimiento para crear un proveedor de tokens de seguridad personalizado.

  3. Opcional. Invalide el método CreateSecurityTokenAuthenticator(SecurityTokenRequirement, SecurityTokenResolver) si se debe crear una implementación de SecurityTokenAuthenticator personalizada. Para más información sobre los autenticadores de tokens de seguridad personalizados, consulte Procedimiento para crear un autenticador de tokens de seguridad personalizado.

  4. Opcional. Invalide el método CreateSecurityTokenSerializer si se debe crear un SecurityTokenSerializer personalizado. Para más información sobre los tokens de seguridad personalizados y los serializadores de tokens de seguridad personalizados, consulte Procedimiento para crear un token personalizado.

    internal class MyClientCredentialsSecurityTokenManager :
        ClientCredentialsSecurityTokenManager
    {
        MyClientCredentials credentials;
    
        public MyClientCredentialsSecurityTokenManager(MyClientCredentials credentials)
            : base(credentials)
        {
            this.credentials = credentials;
        }
    
        public override SecurityTokenProvider CreateSecurityTokenProvider(
            SecurityTokenRequirement tokenRequirement)
        {
            // Return your implementation of the SecurityTokenProvider, if required.
            // This implementation delegates to the base class.
            return base.CreateSecurityTokenProvider(tokenRequirement);
        }
    
        public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(
            SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
        {
            // Return your implementation of the SecurityTokenAuthenticator, if required.
            // This implementation delegates to the base class.
            return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver);
        }
    
        public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
        {
            // Return your implementation of the SecurityTokenSerializer, if required.
            // This implementation delegates to the base class.
            return base.CreateSecurityTokenSerializer(version);
        }
    }
    
    
    Friend Class MyClientCredentialsSecurityTokenManager
        Inherits ClientCredentialsSecurityTokenManager
        Private credentials As MyClientCredentials
    
    
        Public Sub New(ByVal credentials As MyClientCredentials)
            MyBase.New(credentials)
            Me.credentials = credentials
    
        End Sub
    
    
        Public Overrides Function CreateSecurityTokenProvider( _
        ByVal tokenRequirement As SecurityTokenRequirement) As SecurityTokenProvider
            ' Return your implementation of the SecurityTokenProvider, if required.
            ' This implementation delegates to the base class.
            Return MyBase.CreateSecurityTokenProvider(tokenRequirement)
    
        End Function
    
    
        Public Overrides Function CreateSecurityTokenAuthenticator( _
        ByVal tokenRequirement As SecurityTokenRequirement, _
        ByRef outOfBandTokenResolver As SecurityTokenResolver) As SecurityTokenAuthenticator
            ' Return your implementation of the SecurityTokenAuthenticator, if required.
            ' This implementation delegates to the base class.
            Return MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, outOfBandTokenResolver)
    
        End Function
    
    
        Public Overrides Function CreateSecurityTokenSerializer(ByVal version As SecurityTokenVersion) _
        As SecurityTokenSerializer
            ' Return your implementation of the SecurityTokenSerializer, if required.
            ' This implementation delegates to the base class.
            Return MyBase.CreateSecurityTokenSerializer(version)
    
        End Function
    End Class
    

Para usar credenciales de cliente personalizadas a partir del código de la aplicación

  1. Cree una instancia del cliente generado que representa la interfaz de servicio, o cree una instancia del ChannelFactory que señale a un servicio con el que desee comunicarse.

  2. Elimine el comportamiento de credenciales de cliente proporcionadas por el sistema de la colección Behaviors, a la que se puede tener acceso mediante la propiedad Endpoint.

  3. Cree una nueva instancia de una clase de credenciales de cliente personalizada y agréguela a la colección Behaviors, a la que se puede tener acceso mediante la propiedad Endpoint.

    // Create a client with the client endpoint configuration.
    CalculatorClient client = new CalculatorClient();
    
    // Remove the ClientCredentials behavior.
    client.ChannelFactory.Endpoint.Behaviors.Remove<ClientCredentials>();
    
    // Add a custom client credentials instance to the behaviors collection.
    client.ChannelFactory.Endpoint.Behaviors.Add(new MyClientCredentials());
    
    ' Create a client with the client endpoint configuration.
    Dim client As New CalculatorClient()
    
    ' Remove the ClientCredentials behavior.
    client.ChannelFactory.Endpoint.Behaviors.Remove(Of ClientCredentials)()
    
    ' Add a custom client credentials instance to the behaviors collection.
    client.ChannelFactory.Endpoint.Behaviors.Add(New MyClientCredentials())
    

El procedimiento anterior muestra cómo usar las credenciales de cliente del código de aplicación. También se pueden configurar credenciales de WCF usando el archivo de configuración de la aplicación. A menudo, es preferible utilizar la configuración de la aplicación en lugar de emplear codificación de forma rígida, porque permite modificar los parámetros de la aplicación sin tener que modificar la fuente, recompilar y reimplementar.

El siguiente procedimiento describe cómo proporcionar compatibilidad para la configuración de credenciales personalizadas.

Creación de un controlador de configuración para las credenciales de cliente personalizadas

  1. Defina una clase nueva derivada a partir de ClientCredentialsElement.

  2. Opcional. Agregue propiedades para todos los parámetros de configuración adicionales que desee exponer a través de la configuración de la aplicación. El siguiente ejemplo agrega una propiedad denominada CreditCardNumber.

  3. Invalide la propiedad BehaviorType para devolver el tipo de la clase de credenciales de cliente personalizadas creado con el elemento de configuración.

  4. Invalide el método CreateBehavior . El método es responsable de crear y devolver una instancia de la clase de credenciales personalizadas basándose en los ajustes cargados desde el archivo de configuración. Llame al método ApplyConfiguration(ClientCredentials) base desde este método para recuperar los ajustes de credenciales proporcionados por el sistema cargados en su instancia de credenciales de cliente personalizadas.

  5. Opcional. Si agregó propiedades adicionales en el paso 2, ha de invalidar la propiedad Properties para registrar su configuración adicional para que el marco de configuración las reconozca. Combine sus propiedades con las propiedades de clase base para permitir que los ajustes proporcionados por el sistema se configuren a través de este elemento de configuración de credenciales de cliente personalizadas.

    public class MyClientCredentialsConfigHandler : ClientCredentialsElement
    {
        ConfigurationPropertyCollection properties;
    
        public override Type BehaviorType
        {
            get { return typeof(MyClientCredentials); }
        }
    
        public string CreditCardNumber
        {
            get { return (string)base["creditCardNumber"]; }
            set
            {
                if (String.IsNullOrEmpty(value))
                {
                    value = String.Empty;
                }
                base["creditCardNumber"] = value;
            }
        }
    
        protected override ConfigurationPropertyCollection Properties
        {
            get
            {
                if (this.properties == null)
                {
                    ConfigurationPropertyCollection properties = base.Properties;
                    properties.Add(new ConfigurationProperty(
                        "creditCardNumber",
                        typeof(System.String),
                        string.Empty,
                        null,
                        new StringValidator(0, 32, null),
                        ConfigurationPropertyOptions.None));
                    this.properties = properties;
                }
                return this.properties;
            }
        }
    
        protected override object CreateBehavior()
        {
            MyClientCredentials creds = new MyClientCredentials();
            creds.CreditCardNumber = CreditCardNumber;
            base.ApplyConfiguration(creds);
            return creds;
        }
    }
    
    
    Public Class MyClientCredentialsConfigHandler
        Inherits ClientCredentialsElement
        Private propertiesValue As ConfigurationPropertyCollection
    
    
        Public Overrides ReadOnly Property BehaviorType() As Type
            Get
                Return GetType(MyClientCredentials)
            End Get
        End Property
    
        Public Property CreditCardNumber() As String
            Get
                Return CStr(MyBase.Item("creditCardNumber"))
            End Get
            Set
                If String.IsNullOrEmpty(value) Then
                    value = String.Empty
                End If
                MyBase.Item("creditCardNumber") = value
            End Set
        End Property
    
    
        Protected Overrides ReadOnly Property Properties() As ConfigurationPropertyCollection
            Get
                If Me.propertiesValue Is Nothing Then
                    Dim myProperties As ConfigurationPropertyCollection = MyBase.Properties
                    myProperties.Add(New ConfigurationProperty( _
                    "creditCardNumber", _
                    GetType(System.String), _
                    String.Empty, _
                    Nothing, _
                    New StringValidator(0, 32, Nothing), _
                    ConfigurationPropertyOptions.None))
                    Me.propertiesValue = myProperties
                End If
                Return Me.propertiesValue
            End Get
        End Property
    
    
        Protected Overrides Function CreateBehavior() As Object
            Dim creds As New MyClientCredentials()
            creds.CreditCardNumber = Me.CreditCardNumber
            MyBase.ApplyConfiguration(creds)
            Return creds
    
        End Function
    End Class
    

Una vez que tenga tiene la clase del controlador de configuración, puede integrarse en el marco de configuración de WCF. Eso permite que las credenciales de cliente personalizadas se usen en los elementos de comportamiento de extremo de cliente, tal y como se muestra en el siguiente procedimiento.

Para registrar y usar un controlador de configuración de credenciales de cliente personalizadas en la configuración de la aplicación

  1. Agregue un elemento <extensions> y un elemento <behaviorExtensions> al archivo de configuración.

  2. Agregue un elemento <add> al elemento <behaviorExtensions> y establezca el atributo name en un valor adecuado.

  3. Establezca el atributo type en el nombre de tipo completo. Incluya también el nombre de ensamblado y otros atributos de ensamblado.

    <system.serviceModel>
      <extensions>
        <behaviorExtensions>
          <add name="myClientCredentials" type="Microsoft.ServiceModel.Samples.MyClientCredentialsConfigHandler, CustomCredentials, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
        </behaviorExtensions>
      </extensions>
    </system.serviceModel>
    
  4. Después de registrar su controlador de configuración, el elemento de credenciales personalizadas se puede usar dentro del mismo archivo de configuración en lugar del elemento <clientCredentials> proporcionado por el sistema. Puede utilizar las propiedades proporcionadas por el sistema y cualquier propiedad nueva que haya agregado a su implementación del controlador de configuración. El siguiente ejemplo establece el valor de una propiedad personalizada mediante el atributo creditCardNumber.

    <behaviors>
      <endpointBehaviors>
        <behavior name="myClientCredentialsBehavior">
          <myClientCredentials creditCardNumber="123-123-123"/>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    

Para implementar credenciales de servicio personalizadas

  1. Defina una clase nueva derivada a partir de ServiceCredentials.

  2. Opcional. Agregue nuevas propiedades para proporcionar API para los nuevos valores de credenciales que se están agregando. Si no agrega nuevos valores de credenciales, no realice este paso. En el siguiente ejemplo se agrega una propiedad AdditionalCertificate.

  3. Invalide el método CreateSecurityTokenManager . La infraestructura de WCF llama automáticamente a este método cuando se utiliza la credencial de cliente personalizada. El método es responsable de crear y devolver una instancia de una implementación de la clase SecurityTokenManager(descrita en el siguiente procedimiento).

  4. Opcional. Invalide el método CloneCore . Esto sólo se requiere si se agregan nuevas propiedades o campos internos a la implementación de credenciales de cliente personalizadas.

    public class MyServiceCredentials : ServiceCredentials
    {
        X509Certificate2 additionalCertificate;
    
        public MyServiceCredentials()
        {
        }
    
        protected MyServiceCredentials(MyServiceCredentials other)
            : base(other)
        {
            this.additionalCertificate = other.additionalCertificate;
        }
    
        public X509Certificate2 AdditionalCertificate
        {
            get
            {
                return this.additionalCertificate;
            }
            set
            {
                if (value == null)
                {
                    throw new ArgumentNullException("value");
                }
                this.additionalCertificate = value;
            }
        }
    
        public override SecurityTokenManager CreateSecurityTokenManager()
        {
            return base.CreateSecurityTokenManager();
        }
    
        protected override ServiceCredentials CloneCore()
        {
            return new MyServiceCredentials(this);
        }
    }
    
    Public Class MyServiceCredentials
        Inherits ServiceCredentials
        Private additionalCertificateValue As X509Certificate2
    
        Public Sub New()
    
        End Sub
    
        Protected Sub New(ByVal other As MyServiceCredentials)
            MyBase.New(other)
            Me.additionalCertificate = other.additionalCertificate
        End Sub
    
    
        Public Property AdditionalCertificate() As X509Certificate2
            Get
                Return Me.additionalCertificateValue
            End Get
            Set
                If value Is Nothing Then
                    Throw New ArgumentNullException("value")
                End If
                Me.additionalCertificateValue = value
            End Set
        End Property
    
        Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager
            Return MyBase.CreateSecurityTokenManager()
    
        End Function
    
    
        Protected Overrides Function CloneCore() As ServiceCredentials
            Return New MyServiceCredentials(Me)
    
        End Function
    End Class
    

Para implementar un administrador de tokens de seguridad de servicio personalizados

  1. Defina una clase nueva derivada de la clase ServiceCredentialsSecurityTokenManager.

  2. Opcional. Invalide el método CreateSecurityTokenProvider si se debe crear una implementación de SecurityTokenProvider personalizada. Para más información sobre los proveedores de tokens de seguridad personalizados, consulte Procedimiento para crear un proveedor de tokens de seguridad personalizado.

  3. Opcional. Invalide el método CreateSecurityTokenAuthenticator si se debe crear una implementación de SecurityTokenAuthenticator personalizada. Para más información sobre los autenticadores de tokens de seguridad personalizados, consulte el tema Procedimiento para crear un autenticador de tokens de seguridad personalizado.

  4. Opcional. Invalide el método CreateSecurityTokenSerializer(SecurityTokenVersion) si se debe crear un SecurityTokenSerializer personalizado. Para más información sobre los tokens de seguridad personalizados y los serializadores de tokens de seguridad personalizados, consulte Procedimiento para crear un token personalizado.

    internal class MyServiceCredentialsSecurityTokenManager :
        ServiceCredentialsSecurityTokenManager
    {
        MyServiceCredentials credentials;
    
        public MyServiceCredentialsSecurityTokenManager(MyServiceCredentials credentials)
            : base(credentials)
        {
            this.credentials = credentials;
        }
    
        public override SecurityTokenProvider CreateSecurityTokenProvider(SecurityTokenRequirement tokenRequirement)
        {
            // Return your implementation of SecurityTokenProvider, if required.
            // This implementation delegates to the base class.
            return base.CreateSecurityTokenProvider(tokenRequirement);
        }
    
        public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
        {
            // Return your implementation of SecurityTokenProvider, if required.
            // This implementation delegates to the base class.
            return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver);
        }
    
        public override SecurityTokenSerializer CreateSecurityTokenSerializer(SecurityTokenVersion version)
        {
            // Return your implementation of SecurityTokenProvider, if required.
            // This implementation delegates to the base class.
            return base.CreateSecurityTokenSerializer(version);
        }
    }
    
    Friend Class MyServiceCredentialsSecurityTokenManager
        Inherits ServiceCredentialsSecurityTokenManager
        Private credentials As MyServiceCredentials
    
        Public Sub New(ByVal credentials As MyServiceCredentials)
            MyBase.New(credentials)
            Me.credentials = credentials
    
        End Sub
    
    
        Public Overrides Function CreateSecurityTokenProvider(ByVal tokenRequirement As SecurityTokenRequirement) _
        As SecurityTokenProvider
            ' Return your implementation of SecurityTokenProvider, if required.
            ' This implementation delegates to the base class.
            Return MyBase.CreateSecurityTokenProvider(tokenRequirement)
    
        End Function
    
        Public Overrides Function CreateSecurityTokenAuthenticator( _
        ByVal tokenRequirement As SecurityTokenRequirement, _
        ByRef outOfBandTokenResolver As SecurityTokenResolver) _
        As SecurityTokenAuthenticator
            ' Return your implementation of SecurityTokenProvider, if required.
            ' This implementation delegates to the base class.
            Return MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, outOfBandTokenResolver)
    
        End Function
    
    
        Public Overrides Function CreateSecurityTokenSerializer(ByVal version As SecurityTokenVersion) _
        As SecurityTokenSerializer
            ' Return your implementation of SecurityTokenProvider, if required.
            ' This implementation delegates to the base class.
            Return MyBase.CreateSecurityTokenSerializer(version)
    
        End Function
    End Class
    

Para usar credenciales de servicio personalizadas a partir del código de la aplicación

  1. Creación de una instancia de ServiceHost.

  2. Elimine el comportamiento de las credenciales de servicio proporcionadas por el sistema desde la colección Behaviors.

  3. Cree una nueva instancia de la clase de credenciales de servicio personalizadas y agréguela a la colección Behaviors.

    // Create a service host with a service type.
    ServiceHost serviceHost = new ServiceHost(typeof(Service));
    
    // Remove the default ServiceCredentials behavior.
    serviceHost.Description.Behaviors.Remove<ServiceCredentials>();
    
    // Add a custom service credentials instance to the collection.
    serviceHost.Description.Behaviors.Add(new MyServiceCredentials());
    
    ' Create a service host with a service type.
    Dim serviceHost As New ServiceHost(GetType(Service))
    
    ' Remove the default ServiceCredentials behavior.
    serviceHost.Description.Behaviors.Remove(Of ServiceCredentials)()
    
    ' Add a custom service credentials instance to the collection.
    serviceHost.Description.Behaviors.Add(New MyServiceCredentials())
    

Agregue compatibilidad con la configuración mediante los pasos descritos anteriormente en los procedimientos "To create a configuration handler for custom client credentials" y "To register and use a custom client credentials configuration handler in the application configuration". La única diferencia es usar la clase ServiceCredentialsElement en lugar de la clase ClientCredentialsElement como una clase base para el controlador de configuración. El elemento de credencial de servicio personalizado puede utilizarse después dondequiera que se utilice el elemento <serviceCredentials> proporcionado por el sistema.

Consulte también