Поделиться через


Пошаговое руководство. Создание пользовательских учетных данных для клиента и службы

В этом разделе показано, как реализовать пользовательские учетные данные клиента и службы, и как использовать пользовательские учетные данные из кода приложения.

Классы расширяемости учетных данных

Классы ClientCredentials и ServiceCredentials являются основными точками входа для расширяемости безопасности Windows Communication Foundation (WCF). Эти классы учетных данных предоставляют интерфейсы API, позволяющие коду приложения задавать учетные данные и преобразовывать типы учетных данных в маркеры безопасности. (Маркеры безопасности представляют собой форму передачи учетных данных в сообщениях SOAP.) Обязанности этих классов учетных данных можно разделить на две области:

  • предоставление интерфейсов API, позволяющих приложениям задавать учетные данные;

  • выступать в качестве фабрики для реализаций SecurityTokenManager.

И класс ClientCredentials, и класс ServiceCredentials наследуют от абстрактного класса SecurityCredentialsManager, определяющего контракт для возвращения SecurityTokenManager.

Дополнительные сведения о классах учетных данных и их месте в архитектуре безопасности WCF см. в разделе Архитектура безопасности.

Реализации, предусмотренные по умолчанию в WCF, поддерживают предоставляемые системой типы учетных данных и создают диспетчер учетных данных, способный обрабатывать эти типы учетных данных.

Причины для настройки учетных данных

Существует несколько причин настраивать классы учетных данных как клиентов, так и служб. Прежде всего это необходимость изменить по умолчанию правила безопасности WCF в части обработки предоставляемых системой типов учетных данных, особенно по следующим причинам.

  • Изменения, невозможные при использовании других точек расширяемости.

  • Добавление новых типов учетных данных.

  • Добавление новых пользовательских типов маркеров безопасности.

В этом разделе описывается реализация пользовательских учетных данных клиента и службы и их использование из кода приложения.

Дальнейшие шаги

Создание пользовательского класса учетных данных — только первый шаг, поскольку причиной настройки учетных данных является изменение поведения WCF в части выдачи учетных данных, сериализации маркеров безопасности или проверки подлинности. В других подразделах этого раздела описывается создание пользовательских сериализаторов и структур проверки подлинности. В этом отношении создание пользовательского класса учетных данных — первый подраздел серии. Следующие действия (создание пользовательских сериализаторов и структур проверки подлинности) можно предпринимать только после создания пользовательских учетных данных. Содержание данного подраздела продолжают следующие подразделы:

Процедуры

Реализация пользовательских учетных данных клиента

  1. Определите новый класс, производный от класса ClientCredentials.

  2. Необязательно. Добавьте новые методы или свойства для новых типов учетных данных. Если новые типы учетных данных не добавляются, пропустите этот шаг. В следующем примере добавляется свойство CreditCardNumber.

  3. Переопределите метод CreateSecurityTokenManager. Этот метод автоматически вызывается инфраструктурой безопасности WCF при использовании пользовательских учетных данных клиента. Он отвечает за создание и возвращение экземпляра реализации класса SecurityTokenManager.

    ms730868.Important(ru-ru,VS.100).gif Примечание
    Важно отметить, что метод CreateSecurityTokenManager переопределен, чтобы создать пользовательский диспетчер маркеров безопасности. Чтобы создать фактический маркер безопасности, диспетчер маркеров безопасности, производный от ClientCredentialsSecurityTokenManager, должен возвратить пользовательский поставщик маркеров безопасности, производный от SecurityTokenProvider. Если не следовать этому шаблону при создании маркеров безопасности, приложение может работать неправильно, если объекты ChannelFactory кэшируются (кэширование применяется по умолчанию в клиентских прокси WCF). В этом случае также возможна атака с несанкционированным получением прав. Объект пользовательских учетных данных кэшируется в составе ChannelFactory. Однако пользовательский объект SecurityTokenManager создается при каждом вызове, что снижает угрозу безопасности при условии, что в SecurityTokenManager предусмотрена логика создания маркеров.

  4. Переопределите метод 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);
        }
    }
    

Реализация пользовательского клиентского диспетчера маркеров безопасности

  1. Определите новый класс, производный от класса ClientCredentialsSecurityTokenManager.

  2. Необязательно. Переопределите метод CreateSecurityTokenProvider, если необходимо создать пользовательскую реализацию SecurityTokenProvider. Дополнительные сведения о пользовательских поставщиках маркеров безопасности см. в разделе Как создать пользовательский поставщик маркеров безопасности.

  3. Необязательно. Переопределите метод CreateSecurityTokenAuthenticator, если необходимо создать пользовательскую реализацию SecurityTokenAuthenticator. Дополнительные сведения о пользовательских структурах проверки подлинности маркеров безопасности см. в разделе Как создавать пользовательскую структуру проверки подлинности маркера безопасности.

  4. Необязательно. Переопределите метод CreateSecurityTokenSerializer, если необходимо создать пользовательский SecurityTokenSerializer. Дополнительные сведения о пользовательских маркерах безопасности и пользовательских сериализаторах маркеров безопасности см. в разделе Как создавать пользовательский маркер.

    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);
        }
    }
    

Использование пользовательских учетных данных клиента из кода приложения

  1. Создайте экземпляр сформированного клиента, представляющий интерфейс службы, или создайте экземпляр ChannelFactory, указывающий на службу, с которой требуется обмениваться данными.

  2. Удалите предоставляемое системой поведение учетных данных клиента из коллекции Behaviors, обратиться к которой можно через свойство Endpoint.

  3. Создайте новый экземпляр пользовательского класса учетных данных клиента и добавьте его в коллекцию Behaviors, обратиться к которой можно через свойство 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());
    

В приведенной выше процедуре было показано, как использовать учетные данные клиента из кода приложения. Учетные данные WCF также можно настроить с помощью файла конфигурации приложения. Использование конфигурации приложения зачастую предпочтительнее, чем жесткое программирование, поскольку так можно изменять параметры приложения без внесения изменений в исходный код, повторной компиляции и повторного развертывания.

В следующей процедуре показано, как обеспечить поддержку конфигурации пользовательских учетных данных.

Создание обработчика конфигурации для пользовательских учетных данных клиента

  1. Определите новый производный класс от класса ClientCredentialsElement.

  2. Необязательно. Добавьте свойства для всех дополнительных параметров конфигурации, к которым требуется предоставить доступ через конфигурацию приложения. В приведенном ниже примере добавляется одно свойство с именем CreditCardNumber.

  3. Переопределите свойство BehaviorType так, чтобы оно возвращало тип пользовательского класса учетных данных клиента, создаваемый элементом конфигурации.

  4. Переопределите метод CreateBehavior. Этот метод отвечает за создание и возвращение экземпляра пользовательского класса учетных данных на основании параметров, загруженных и файла конфигурации. Вызовите из этого метода базовый метод ApplyConfiguration, чтобы извлечь предоставляемые системой параметры учетных данных, загруженные в экземпляр пользовательских учетных данных клиента.

  5. Необязательно. Если вы добавляли дополнительные свойства на шаге 2, необходимо переопределить свойство Properties для регистрации дополнительных параметров конфигурации, чтобы они распознавались инфраструктурой конфигураций. Объедините добавленные свойства со свойствами базового класса, чтобы разрешить настройку предоставляемых системой параметров посредством данного элемента конфигурации пользовательских учетных данных клиента.

    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;
        }
    }
    

После создания класса обработчика конфигурации его можно интегрировать в инфраструктуру конфигураций WCF. Это позволяет использовать пользовательские учетные данные клиента в элементах поведения конечной точки клиента, как показано в следующей процедуре.

Регистрация и использование обработчика конфигурации для пользовательских учетных данных клиента в конфигурации приложения

  1. Добавьте элемент <extensions> и элемент <behaviorExtensions> в файл конфигурации.

  2. Добавьте элемент <add> в элемент <behaviorExtensions> и присвойте соответствующее значение атрибуту name.

  3. Присвойте атрибуту type полное имя типа. Включите также имя сборки и другие атрибуты сборки.

    <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. После регистрации обработчика конфигурации элемент пользовательских учетных данных можно использовать внутри того же файла конфигурации вместо предоставляемого системой элемента <clientCredentials>. Можно использовать как предоставляемые системой свойства, так и любые новые свойства, добавленные в реализацию обработчика конфигурации. В следующем примере с помощью атрибута creditCardNumber задается значение пользовательского свойства.

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

Реализация пользовательских учетных данных службы

  1. Определите новый класс, производный от класса ServiceCredentials.

  2. Необязательно. Добавьте новые свойства, чтобы предоставить интерфейсы API для добавляемых новых значений учетных данных. Если новые значения учетных данных не добавляются, пропустите этот шаг. В следующем примере добавляется свойство AdditionalCertificate.

  3. Переопределите метод CreateSecurityTokenManager. Этот метод автоматически вызывается инфраструктурой WCF при использовании пользовательских учетных данных клиента. Он отвечает за создание и возвращение экземпляра реализации класса SecurityTokenManager (рассматривается в следующей процедуре).

  4. Необязательно. Переопределите метод CloneCore. Это необходимо только при добавлении новых свойств или внутренних полей в реализацию пользовательских учетных данных клиента.

    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);
        }
    }
    

Реализация пользовательского диспетчера маркеров безопасности службы

  1. Определите новый класс, производный от класса ServiceCredentialsSecurityTokenManager.

  2. Необязательно. Переопределите метод CreateSecurityTokenProvider, если необходимо создать пользовательскую реализацию SecurityTokenProvider. Дополнительные сведения о пользовательских поставщиках маркеров безопасности см. в разделе Как создать пользовательский поставщик маркеров безопасности.

  3. Необязательно. Переопределите метод CreateSecurityTokenAuthenticator, если необходимо создать пользовательскую реализацию SecurityTokenAuthenticator. Дополнительные сведения о пользовательских структурах проверки подлинности маркеров безопасности см. в разделе Как создавать пользовательскую структуру проверки подлинности маркера безопасности.

  4. Необязательно. Переопределите метод CreateSecurityTokenSerializer, если необходимо создать пользовательский SecurityTokenSerializer. Дополнительные сведения о пользовательских маркерах безопасности и пользовательских сериализаторах маркеров безопасности см. в разделе Как создавать пользовательский маркер.

    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);
        }
    }
    

Использование пользовательских учетных данных службы из кода приложения

  1. Создайте экземпляр класса ServiceHost.

  2. Удалите предоставляемое системой поведение учетных данных службы из коллекции Behaviors.

  3. Создайте новый экземпляр пользовательского класса учетных данных службы и добавьте его в коллекцию 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());
    

Добавьте поддержку конфигурации, выполнив действия, описанные ранее в процедурах «To create a configuration handler for custom client credentials» и «To register and use a custom client credentials configuration handler in the application configuration». Единственное отличие состоит в использовании в качестве базового класса для обработчика конфигурации класса ServiceCredentialsElement вместо класса ClientCredentialsElement. После этого элемент пользовательских учетных данных службы можно использовать везде, где используется предоставляемый системой элемент <serviceCredentials>.

См. также

Задачи

Как создать пользовательский поставщик маркеров безопасности

Справочник

ClientCredentials
ServiceCredentials
SecurityCredentialsManager
SecurityTokenManager
ClientCredentialsElement
ServiceCredentialsElement

Основные понятия

Как создавать пользовательскую структуру проверки подлинности маркера безопасности
Как создавать пользовательский маркер