Condividi tramite


Procedura: usare un validator di nome utente e password personalizzato

Per impostazione predefinita, quando per l'autenticazione vengono utilizzati un nome utente e una password, in Windows Communication Foundation (WCF) viene utilizzato Windows per convalidarli. Tuttavia, WCF consente l'utilizzo di schemi personalizzati di autenticazione di nome utente e password, noti come validator. Per incorporare un validator personalizzato di nome utente e password, creare una classe che deriva da UserNamePasswordValidator e configurarla.

Per un'applicazione di esempio, vedere Validator del nome utente e password.

Per creare un validator di nome utente e password personalizzato

  1. Creare una classe che deriva da UserNamePasswordValidator.

    
    public class CustomUserNameValidator : UserNamePasswordValidator
    {
    
    Public Class CustomUserNameValidator
        Inherits UserNamePasswordValidator
    
  2. Implementare lo schema di autenticazione personalizzato eseguendo l'override del metodo Validate.

    Non utilizzare il codice contenuto nell'esempio seguente, che esegue l'override del metodo Validate, in un ambiente di produzione. Sostituire il codice con lo schema di convalida di nome utente e password personalizzato, operazione che potrebbe comportare il recupero di coppie di nome utente e password da un database.

    Affinché gli errori di autenticazione vengano restituiti al client, generare una classe FaultException nel metodo 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
    

Per configurare un servizio per l'utilizzo di un validator di nome utente e password personalizzato

  1. Configurare un'associazione che utilizza meccanismi di sicurezza a livello di messaggio su qualsiasi trasporto o meccanismi di sicurezza a livello di trasporto su HTTP(S).

    Quando si utilizza la modalità di sicurezza dei messaggi, aggiungere uno dei binding forniti dal sistema, come <wsHttpBinding>, o <customBinding> che supporta la modalità di sicurezza dei messaggi e il tipo di credenziale UserName.

    Quando si usa la sicurezza a livello di trasporto su HTTP(S), aggiungere <wsHttpBinding> o <basicHttpBinding>, un <netTcpBinding> o un <customBinding> che usa HTTP(S) e lo schema di autenticazione Basic.

    Nota

    Quando si utilizza .NET Framework 3.5 o versioni successive, è possibile utilizzare un validator di nome utente e password personalizzato con modalità di sicurezza dei messaggi e del trasporto. Quando si utilizza WinFX, un validator di nome utente e password personalizzato può essere utilizzato solo con la modalità di sicurezza dei messaggi.

    Suggerimento

    Per ulteriori informazioni sull'utilizzo di <netTcpBinding> in questo contesto, vedere <Sicurezza>.

    1. Nel file di configurazione, sotto l'elemento <system.serviceModel>, aggiungere un elemento <bindings>.

    2. Aggiungere un elemento <wsHttpBinding> o <basicHttpBinding> alla sezione delle associazioni. Per altre informazioni sulla creazione di un elemento di associazione WCF, vedere Procedura: Specificare un'associazione al servizio nella configurazione.

    3. Impostare l'attributo mode di <security> o <security> su Message, Transporto .TransportWithMessageCredential.

    4. Impostare l'attributo clientCredentialType di <message> o <transport>.

      Quando si utilizza la modalità di sicurezza dei messaggi, impostare l'attributo clientCredentialType dell'elemento <message> su UserName.

      Quando si utilizza la modalità di sicurezza a livello di trasporto su HTTP(S), impostare l'attributo clientCredentialType dell'elemento <transport> o <transport> su Basic.

      Nota

      Quando un servizio WCF è ospitato in Internet Information Services (IIS) utilizzando la protezione a livello di trasporto e la proprietà UserNamePasswordValidationMode è impostata su Custom, lo schema di autenticazione personalizzato utilizza un sottoinsieme dell'autenticazione di Windows. Questo avviene perché in tale scenario IIS esegue l'autenticazione di Windows prima che WCF richiami l'autenticatore personalizzato.

    Per altre informazioni sulla creazione di un elemento di associazione WCF, vedere Procedura: Specificare un'associazione al servizio nella configurazione.

    Nell'esempio seguente viene illustrato il codice di configurazione per l'associazione:

    <system.serviceModel>
      <bindings>
      <wsHttpBinding>
          <binding name="Binding1">
            <security mode="Message">
              <message clientCredentialType="UserName" />
            </security>
          </binding>
        </wsHttpBinding>
      </bindings>
    </system.serviceModel>
    
  2. Configurare un comportamento che specifica che un validator personalizzato di nome utente e password viene utilizzato per convalidare coppie di nome utente e password per i token di sicurezza UserNameSecurityToken in arrivo.

    1. Come figlio per l'elemento <system.serviceModel>, aggiungere un elemento <behaviors>.

    2. Aggiungere un <serviceBehaviors> all'elemento <behaviors>.

    3. Aggiungere un elemento <behavior> e impostare l'attributo name su un valore appropriato.

    4. Aggiungere <serviceCredentials> all'elemento <behavior>.

    5. Aggiungere un <userNameAuthentication> a <serviceCredentials>.

    6. Imposta userNamePasswordValidationMode su Custom.

      Importante

      Se il valore userNamePasswordValidationMode non è impostato, in WCF viene utilizzata l'autenticazione di Windows anziché il validator personalizzato di nome utente e password.

    7. Impostare customUserNamePasswordValidatorType sul tipo che rappresenta il validator personalizzato di nome utente e password.

    Nell'esempio seguente viene illustrato il frammento <serviceCredentials> fino a questo punto:

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

Esempio

Nel codice di esempio seguente viene dimostrato come creare un validator personalizzato di nome utente e password. Non utilizzare il codice che esegue l'override del metodo Validate in un ambiente di produzione. Sostituire il codice con lo schema di convalida di nome utente e password personalizzato, operazione che potrebbe comportare il recupero di coppie di nome utente e password da un database.

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

Vedi anche