Практическое руководство. Использование пользовательского проверяющего элемента управления для имени пользователя и пароля

По умолчанию, когда имя пользователя и пароль используются для проверки подлинности, Windows Communication Foundation (WCF) использует Windows для проверки имени пользователя и пароля. Тем не менее WCF позволяет использовать пользовательские схемы проверки имени пользователя и пароля, также известные как проверяющие элементы. Чтобы внедрить пользовательский проверяющий элемент управления для проверки подлинности имени пользователя и пароля, необходимо создать класс, унаследованный от класса UserNamePasswordValidator, и настроить его.

Пример приложения см. в разделе "Проверка пароля имени пользователя".

Создание пользовательского проверяющего элемента управления для имени пользователя и пароля

  1. Создайте класс, наследующий от класса UserNamePasswordValidator.

    
    public class CustomUserNameValidator : UserNamePasswordValidator
    {
    
    Public Class CustomUserNameValidator
        Inherits UserNamePasswordValidator
    
  2. Реализуйте пользовательскую схему проверки подлинности, переопределив метод Validate.

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

    Чтобы вернуть ошибки проверки подлинности клиенту, создайте исключение FaultException в методе Validate.

    // This method validates users. It allows in two users, test1 and test2
    // with passwords 1tset and 2tset respectively.
    // This code is for illustration purposes only and
    // must not be used in a production environment because it is not secure.
    public override void Validate(string userName, string password)
    {
        if (null == userName || null == password)
        {
            throw new ArgumentNullException();
        }
    
        if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
        {
            // This throws an informative fault to the client.
            throw new FaultException("Unknown Username or Incorrect Password");
            // When you do not want to throw an informative fault to the client,
            // throw the following exception.
            // throw new SecurityTokenException("Unknown Username or Incorrect Password");
        }
    }
    
    ' This method validates users. It allows in two users, test1 and test2
    ' with passwords 1tset and 2tset respectively.
    ' This code is for illustration purposes only and
    ' must not be used in a production environment because it is not secure.
    Public Overrides Sub Validate(ByVal userName As String, ByVal password As String)
        If Nothing = userName OrElse Nothing = password Then
            Throw New ArgumentNullException()
        End If
    
        If Not (userName = "test1" AndAlso password = "[PLACEHOLDER]") AndAlso Not (userName = "test2" AndAlso password = "[PLACEHOLDER]") Then
            ' This throws an informative fault to the client.
            Throw New FaultException("Unknown Username or Incorrect Password")
            ' When you do not want to throw an informative fault to the client,
            ' throw the following exception:
            ' Throw New SecurityTokenException("Unknown Username or Incorrect Password")
        End If
    
    End Sub
    

Настройка службы для использования пользовательского проверяющего элемента управления для проверки имени пользователя и пароля

  1. Настройте привязку, использующую безопасность сообщений с любым транспортом или безопасность на уровне транспорта по HTTP(S).

    При использовании безопасности сообщений добавьте одну из системных привязок, например <wsHttpBinding или <customBinding>>, которая поддерживает безопасность сообщений и UserName тип учетных данных.

    При использовании безопасности на уровне транспорта по протоколу HTTP(S) добавьте wsHttpBinding или <basicHttpBinding>>, netTcpBinding или< customBinding>>, <использующую протокол HTTP(S) и схему Basic проверки подлинности.<

    Примечание.

    При использовании платформа .NET Framework версии 3.5 или более поздней версии можно использовать настраиваемый проверяющий имя пользователя и пароль с безопасностью сообщений и транспорта. С помощью WinFX настраиваемый проверяющий имя пользователя и пароль можно использовать только с безопасностью сообщений.

    Совет

    Дополнительные сведения об использовании netTcpBinding> в этом контексте см. в разделе <"Безопасность>".<

    1. В файле конфигурации в элементе system.serviceModel> добавьте< элемент bindings>.<

    2. Добавьте элемент wsHttpBinding или <basicHttpBinding>> в раздел привязок.< Дополнительные сведения о создании элемента привязки WCF см. в разделе "Практическое руководство. Указание привязки службы в конфигурации".

    3. mode Задайте для атрибута <безопасности или< безопасности>Message>значение , Transportили .TransportWithMessageCredential

    4. clientCredentialType Задайте атрибут< сообщения> или <транспорта.>

      При использовании безопасности сообщений задайте clientCredentialType для атрибута <сообщения>UserNameзначение .

      При использовании безопасности на уровне транспорта по протоколу HTTP(S) задайте clientCredentialType для атрибута <транспорта или< транспорта Basic>>значение.

      Примечание.

      Если служба WCF размещена в службы IIS (IIS) с помощью безопасности на уровне транспорта и UserNamePasswordValidationMode для свойства задано Customзначение, пользовательская схема проверки подлинности использует подмножество проверка подлинности Windows. Это связано с тем, что в этом сценарии СЛУЖБЫ IIS выполняют проверка подлинности Windows до вызова пользовательского средства проверки подлинности WCF.

    Дополнительные сведения о создании элемента привязки WCF см. в разделе "Практическое руководство. Указание привязки службы в конфигурации".

    В следующем примере показан код конфигурации для привязки:

    <system.serviceModel>
      <bindings>
      <wsHttpBinding>
          <binding name="Binding1">
            <security mode="Message">
              <message clientCredentialType="UserName" />
            </security>
          </binding>
        </wsHttpBinding>
      </bindings>
    </system.serviceModel>
    
  2. Настройте поведение, которое будет указывать, что для проверки пар имени пользователя и пароля для входящих маркеров безопасности UserNameSecurityToken будет использоваться пользовательский проверяющий элемент управления.

    1. В качестве дочернего элемента system.serviceModel> добавьте< элемент behaviors>.<

    2. Добавьте serviceBehaviors> в <элемент behaviors>.<

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

    4. Добавьте serviceCredentials> в <элемент поведения>.<

    5. Добавьте userNameAuthentication> в <serviceCredentials>.<

    6. Задайте для userNamePasswordValidationMode значение Custom.

      Внимание

      userNamePasswordValidationMode Если значение не задано, WCF использует проверка подлинности Windows вместо пользовательского имени пользователя и проверяющего пароля.

    7. Присвойте атрибуту customUserNamePasswordValidatorType значение типа вашего пользовательского проверяющего элемента управления для проверки имени пользователя и пароля.

    В следующем примере показан <serviceCredentials> фрагмент до этой точки:

    <serviceCredentials>
      <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.CalculatorService.CustomUserNameValidator, service" />
    </serviceCredentials>
    

Пример

В следующем примере кода показано, как создать пользовательский проверяющий элемент управления для проверки имени пользователя и пароля. Не используйте код, переопределяющий метод Validate, в производственной среде. Замените код на свою собственную схему проверки подлинности имени пользователя и пароля, в которой может применяться извлечение пар имени пользователя и пароля из базы данных.

using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;

using System.Security.Principal;

using System.ServiceModel;
Imports System.IdentityModel.Selectors
Imports System.IdentityModel.Tokens

Imports System.Security.Principal

Imports System.ServiceModel

public class CustomUserNameValidator : UserNamePasswordValidator
{
    // This method validates users. It allows in two users, test1 and test2
    // with passwords 1tset and 2tset respectively.
    // This code is for illustration purposes only and
    // must not be used in a production environment because it is not secure.
    public override void Validate(string userName, string password)
    {
        if (null == userName || null == password)
        {
            throw new ArgumentNullException();
        }

        if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
        {
            // This throws an informative fault to the client.
            throw new FaultException("Unknown Username or Incorrect Password");
            // When you do not want to throw an informative fault to the client,
            // throw the following exception.
            // throw new SecurityTokenException("Unknown Username or Incorrect Password");
        }
    }
}
Public Class CustomUserNameValidator
    Inherits UserNamePasswordValidator
    ' This method validates users. It allows in two users, test1 and test2
    ' with passwords 1tset and 2tset respectively.
    ' This code is for illustration purposes only and
    ' must not be used in a production environment because it is not secure.
    Public Overrides Sub Validate(ByVal userName As String, ByVal password As String)
        If Nothing = userName OrElse Nothing = password Then
            Throw New ArgumentNullException()
        End If

        If Not (userName = "test1" AndAlso password = "[PLACEHOLDER]") AndAlso Not (userName = "test2" AndAlso password = "[PLACEHOLDER]") Then
            ' This throws an informative fault to the client.
            Throw New FaultException("Unknown Username or Incorrect Password")
            ' When you do not want to throw an informative fault to the client,
            ' throw the following exception:
            ' Throw New SecurityTokenException("Unknown Username or Incorrect Password")
        End If

    End Sub
End Class

См. также