Condividi tramite


Delega e rappresentazione con WCF

Larappresentazione è una tecnica comune utilizzata dai servizi per limitare l'accesso dei client alle risorse del dominio del servizio. Tali risorse possono essere risorse del computer, ad esempio file locali (rappresentazione), o risorse in un'altro computer, ad esempio una condivisione file (delega). Per un'applicazione di esempio, vedere Impersonating the Client. Per un esempio di come usare la rappresentazione, vedere How to: Impersonate a Client on a Service.

Importante

Tenere presente che, in caso di rappresentazione di un client in un servizio, il servizio viene eseguito con le credenziali client, che potrebbero prevedere privilegi più elevati rispetto al processo server.

Panoramica

In genere, i client chiamano un servizio per l’esecuzione di determinate operazioni da parte del servizio stesso per loro conto. La rappresentazione consente al servizio di eseguire azioni per conto del client. La delega consente a un servizio front end di inoltrare le richieste del client ad un servizio back end in modo tale che quest'ultimo possa anche rappresentare il client. La rappresentazione, in genere, viene utilizzata per controllare se un client è autorizzato ad eseguire una particolare azione, mentre la delega è un modo per propagare ad un servizio back end le funzionalità della rappresentazione insieme all'identità del client. La delega è una funzionalità di dominio Windows che può essere utilizzata quando viene eseguita l'autenticazione basata su Kerberos. La delega si differenzia dal flusso dell'identità ed è un'operazione con privilegi maggiori in quanto trasferisce la possibilità di rappresentare il client senza il possesso della relativa password.

Sia la rappresentazione che la delega richiedono che il client abbia una identità di Windows. Se un client non possiede un'identità di Windows, l'unica opzione disponibile è propagare l'identità del client al secondo servizio.

Nozioni fondamentali sulla rappresentazione

Windows Communication Foundation (WCF) supporta la rappresentazione per un'ampia gamma di credenziali client. In questo argomento viene descritto il supporto del modello di servizio per la rappresentazione del chiamante durante l'implementazione di un metodo del servizio. Vengono inoltre descritti gli scenari di distribuzione più frequenti che riguardando la rappresentazione e la sicurezza SOAP, nonché le opzioni WCF in tali scenari.

Questo argomento si incentra sulla rappresentazione e la delega in WCF in caso di uso della sicurezza SOAP. È possibile usare la rappresentazione e la delega con WCF anche quando si usa la sicurezza del trasporto, come descritto in Uso della rappresentazione con la protezione del trasporto.

Due metodi

La sicurezza SOAP in WCF prevede due metodi distinti per eseguire la rappresentazione Il metodo utilizzato dipende dall'associazione. Il primo consiste nella rappresentazione da un token di Windows ottenuto dall'autenticazione Security Support Provider Interface (SSPI) o Kerberos, che viene quindi memorizzato nella cache del servizio. Il secondo consiste nella rappresentazione da un token di Windows ottenuto dalle estensioni Kerberos, collettivamente denominate Service-for-User (S4U).

Rappresentazione con un token memorizzato nella cache

È possibile eseguire la rappresentazione con un token memorizzato nella cache con gli elementi seguenti:

Rappresentazione basata su S4U.

È possibile eseguire la rappresentazione basata su S4U con gli elementi seguenti:

  • WSHttpBinding, WSDualHttpBindinge NetTcpBinding con una credenziale client basata su certificato di cui il servizio può eseguire il mapping a un account di Windows valido.

  • Qualsiasi CustomBinding che utilizza una credenziale client di Windows con la proprietà requireCancellation impostata su false

  • Qualsiasi CustomBinding che utilizza una credenziale client di Windows o basata sul nome utente e una conversazione protetta con la proprietà requireCancellation impostata su false.

La misura in cui il servizio può eseguire la rappresentazione del client dipende dai privilegi di cui dispone l'account del servizio quando tenta la rappresentazione, dal tipo di rappresentazione utilizzato ed eventualmente dall'ambito di rappresentazione consentito dal client.

Nota

Quando il client e il servizio sono in esecuzione nello stesso computer e il client è in esecuzione con un account del sistema (ad esempio Local System o Network Service), il client non può essere rappresentato quando viene stabilita una sessione protetta con token del contesto di sicurezza con stato. Un'applicazione Windows Form o console viene in genere eseguita con l'account attualmente connesso e quindi l'account può essere rappresentato per impostazione predefinita. Tuttavia, quando il client è una pagina ASP:NET ospitata in IIS 6.0 o IIS 7.0, il client viene eseguito con l'account Network Service per impostazione predefinita. Tutte le associazioni fornite dal sistema che supportano le sessioni protette utilizzano un token del contesto di sicurezza (SCT) senza stato per impostazione predefinita. Tuttavia, se il client è una pagina ASP.NET e si usano sessioni protette con token SCT con stato, non è possibile eseguire la rappresentazione del client. Per altre informazioni sull'uso di un token SCT con stato in una sessione protetta, vedere Procedura: Creare un token di contesto di sicurezza per una sessione sicura.

Rappresentazione in un metodo del servizio: modello dichiarativo

La maggior parte degli scenari di rappresentazione implicano l'esecuzione del metodo del servizio nel contesto del chiamante. WCF fornisce una funzionalità di rappresentazione che semplifica questa operazione consentendo all'utente di specificare il requisito di rappresentazione nell'attributo OperationBehaviorAttribute. Ad esempio, nel codice seguente, l'infrastruttura WCF rappresenta il chiamante prima di eseguire il metodo Hello. Qualsiasi tentativo di accedere a risorse native nel metodo Hello ha esito positivo solo se l'elenco di controllo di accesso (ACL) della risorsa consente al chiamante i privilegi di accesso. Per attivare la rappresentazione, impostare la proprietà Impersonation su uno dei valori dell'enumerazione ImpersonationOption , ovvero ImpersonationOption.Required o ImpersonationOption.Allowed, come illustrato nell'esempio seguente.

Nota

Quando un servizio dispone di credenziali più elevate del client remoto, vengono utilizzate le credenziali del servizio se la proprietà Impersonation è impostata su Allowed. In altri termini, se un utente con privilegi di basso livello fornisce le sue credenziali, un servizio con privilegi di livello più elevato esegue il metodo con le credenziali del servizio e può utilizzare risorse che l'utente con privilegi di basso livello non sarebbe altrimenti in grado di utilizzare.

[ServiceContract]
public interface IHelloContract
{
    [OperationContract]
    string Hello(string message);
}

public class HelloService : IHelloService
{
    [OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string Hello(string message)
    {
        return "hello";
    }
}

<ServiceContract()> _
Public Interface IHelloContract
    <OperationContract()> _
    Function Hello(ByVal message As String) As String
End Interface


Public Class HelloService
    Implements IHelloService

    <OperationBehavior(Impersonation:=ImpersonationOption.Required)> _
    Public Function Hello(ByVal message As String) As String Implements IHelloService.Hello
        Return "hello"
    End Function
End Class

L'infrastruttura WCF può rappresentare il chiamante solo se il chiamante viene autenticato con credenziali di cui è possibile eseguire il mapping a un account utente di Windows. Se il servizio è configurato per l'autenticazione con una credenziale di cui non è possibile eseguire il mapping a un account di Windows, il metodo del servizio non viene eseguito.

Nota

In Windows XP, se viene creato un token SCT con stato, la rappresentazione ha esito negativo, generando InvalidOperationException. Per altre informazioni, vedere Scenari non supportati.

Rappresentazione in un metodo del servizio: modello imperativo

Talvolta, per funzionare, non è necessario che un chiamante rappresenti l'intero metodo del servizio, ma solo una parte. In questo caso, è possibile ottenere l'identità Windows del chiamante nel metodo del servizio ed eseguire la rappresentazione in modo imperativo. A tale scopo, utilizzare la proprietà WindowsIdentity della classe ServiceSecurityContext per restituire un'istanza della classe WindowsIdentity e chiamare il metodo Impersonate prima di utilizzare l'istanza.

Nota

Assicurarsi di usare l'istruzione Using di Visual Basic o l'istruzione using di C# per ripristinare automaticamente l'azione di rappresentazione. Se non si usa l'istruzione o se si usa un linguaggio di programmazione diverso da Visual Basic o C#, accertarsi di ripristinare il livello di rappresentazione. In caso contrario, si stabilisce la base per attacchi Denial of service e di elevazione del privilegio.

public class HelloService : IHelloService
{
    [OperationBehavior]
    public string Hello(string message)
    {
        WindowsIdentity callerWindowsIdentity =
        ServiceSecurityContext.Current.WindowsIdentity;
        if (callerWindowsIdentity == null)
        {
            throw new InvalidOperationException
           ("The caller cannot be mapped to a WindowsIdentity");
        }
        using (callerWindowsIdentity.Impersonate())
        {
            // Access a file as the caller.
        }
        return "Hello";
    }
}
Public Class HelloService
    Implements IHelloService

    <OperationBehavior()> _
    Public Function Hello(ByVal message As String) As String _
       Implements IHelloService.Hello
        Dim callerWindowsIdentity As WindowsIdentity = _
            ServiceSecurityContext.Current.WindowsIdentity
        If (callerWindowsIdentity Is Nothing) Then
            Throw New InvalidOperationException( _
              "The caller cannot be mapped to a WindowsIdentity")
        End If
        Dim cxt As WindowsImpersonationContext = callerWindowsIdentity.Impersonate()
        Using (cxt)
            ' Access a file as the caller.
        End Using

        Return "Hello"

    End Function
End Class

Rappresentazione per tutti i metodi del servizio

In alcuni casi, è necessario eseguire tutti i metodi di un servizio nel contesto del chiamante. Anziché attivare in modo esplicito questa funzionalità sulla base di ciascun metodo, utilizzare la classe ServiceAuthorizationBehavior. Impostare la proprietà ImpersonateCallerForAllOperations su true, come illustrato nel codice seguente. La classe ServiceAuthorizationBehavior viene recuperata dalle raccolte di comportamenti della classe ServiceHost . Si noti inoltre che anche la proprietà Impersonation della classe OperationBehaviorAttribute applicata a ogni metodo deve essere impostata su Allowed o Required.

// Code to create a ServiceHost not shown.
ServiceAuthorizationBehavior MyServiceAuthorizationBehavior =
    serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
MyServiceAuthorizationBehavior.ImpersonateCallerForAllOperations = true;
' Code to create a ServiceHost not shown.
Dim MyServiceAuthorizationBehavior As ServiceAuthorizationBehavior
MyServiceAuthorizationBehavior = serviceHost.Description.Behaviors.Find _
(Of ServiceAuthorizationBehavior)()
MyServiceAuthorizationBehavior.ImpersonateCallerForAllOperations = True

Nella tabella seguente viene descritto il comportamento di WCF per tutte le possibili combinazioni di ImpersonationOption e ImpersonateCallerForAllServiceOperations.

ImpersonationOption ImpersonateCallerForAllServiceOperations Comportamento
Richiesto n/d WCF rappresenta il chiamante
Consentito false WCF non rappresenta il chiamante
Consentito true WCF rappresenta il chiamante
NotAllowed false WCF non rappresenta il chiamante
NotAllowed true Non consentita (verrà generata un'eccezione InvalidOperationException ).

Livello di rappresentazione ottenuto dalla rappresentazione con credenziali di Windows e con un token memorizzato nella cache

In alcuni scenari il client dispone di un controllo parziale sul livello di rappresentazione eseguito dal servizio quando si utilizza una credenziale client di Windows. Uno scenario si ha quando il client specifica un livello di rappresentazione anonimo, l'altro quando si esegue la rappresentazione con un token memorizzato nella cache. A tale scopo, impostare la proprietà AllowedImpersonationLevel della classe WindowsClientCredential , a cui si accede come proprietà della classe generica ChannelFactory<TChannel> .

Nota

Quando si specifica un livello di rappresentazione anonimo, il client accede al servizio in modo anonimo. Il servizio deve pertanto consentire gli accessi anonimi, indipendentemente dal fatto che venga eseguita o meno la rappresentazione.

Il client può specificare il livello di rappresentazione come Anonymous, Identification, Impersonationo Delegation. Al livello specificato viene prodotto solo un token, come illustrato nel codice seguente.

ChannelFactory<IEcho> cf = new ChannelFactory<IEcho>("EchoEndpoint");
cf.Credentials.Windows.AllowedImpersonationLevel  =
    System.Security.Principal.TokenImpersonationLevel.Impersonation;
Dim cf As ChannelFactory(Of IEcho) = New ChannelFactory(Of IEcho)("EchoEndpoint")
cf.Credentials.Windows.AllowedImpersonationLevel = _
System.Security.Principal.TokenImpersonationLevel.Impersonation

Nella tabella seguente viene indicato il livello di rappresentazione ottenuto dal servizio in caso di rappresentazione da un token memorizzato nella cache.

Valore AllowedImpersonationLevel Il servizio dispone di SeImpersonatePrivilege Servizio e client con funzionalità di delega ImpersonationLevel
Anonimo n/d Rappresentazione
Anonimo No n/d Identificazione
Identificazione n/d n/d Identificazione
Rappresentazione n/d Rappresentazione
Rappresentazione No n/d Identificazione
Delega Delega
Delega No Rappresentazione
Delega No n/d Identificazione

Livello di rappresentazione ottenuto dalla rappresentazione con credenziali basate sul nome utente e con un token memorizzato nella cache

Passando al servizio il nome utente e la password, un client consente a WCF di accedere come tale utente, il che equivale a impostare la proprietà AllowedImpersonationLevel su Delegation (la proprietà AllowedImpersonationLevel è disponibile sulle classi WindowsClientCredential e HttpDigestClientCredential). Nella tabella seguente viene indicato il livello di rappresentazione ottenuto quando il servizio riceve credenziali basate sul nome utente.

AllowedImpersonationLevel Il servizio dispone di SeImpersonatePrivilege Servizio e client con funzionalità di delega ImpersonationLevel
n/d Delega
n/d No Rappresentazione
n/d No n/d Identificazione

Livello di rappresentazione ottenuto dalla rappresentazione basata su S4U

Il servizio dispone di SeTcbPrivilege Il servizio dispone di SeImpersonatePrivilege Servizio e client con funzionalità di delega ImpersonationLevel
n/d Rappresentazione
No n/d Identificazione
No n/d n/d Identificazione

Mapping di un certificato client a un account di Windows

È possibile effettuare l'autenticazione di un client a un servizio tramite un certificato e fare in modo che il servizio esegua il mapping del client a un account esistente tramite Active Directory. Nel codice XML seguente viene illustrato come configurare il servizio affinché esegua il mapping del certificato.

<behaviors>  
  <serviceBehaviors>  
    <behavior name="MapToWindowsAccount">  
      <serviceCredentials>  
        <clientCertificate>  
          <authentication mapClientCertificateToWindowsAccount="true" />  
        </clientCertificate>  
      </serviceCredentials>  
    </behavior>  
  </serviceBehaviors>  
</behaviors>  

Nel codice seguente viene illustrato come configurare il servizio.

// Create a binding that sets a certificate as the client credential type.  
WSHttpBinding b = new WSHttpBinding();  
b.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;  
  
// Create a service host that maps the certificate to a Windows account.  
Uri httpUri = new Uri("http://localhost/Calculator");  
ServiceHost sh = new ServiceHost(typeof(HelloService), httpUri);  
sh.Credentials.ClientCertificate.Authentication.MapClientCertificateToWindowsAccount = true;  

Delega

Per delegare ad un servizio back end, è necessario che un servizio esegua l'autenticazione multifase Kerberos (SSPI senza fallback NTLM) o l'autenticazione Kerberos diretta ad un servizio back end utilizzando l'identità Windows del client. Per delegare ad un servizio back-end, creare una classe ChannelFactory<TChannel> e un canale, quindi comunicare tramite il canale durante la rappresentazione del client. Con questo tipo di delega, la distanza con la quale deve essere posizionato il servizio back end dal servizio front end dipende dal livello di rappresentazione raggiunto dal servizio front end. Se il livello di rappresentazione è Impersonation, è necessario che i servizi front end e back end vengano eseguiti nello stesso computer. Se il livello di rappresentazione è Delegation, i servizi front end e back end possono essere eseguiti in computer diversi o nello stesso computer. L'attivazione della rappresentazione a livello di delega richiede che, per consentire la delega, i criteri di dominio di Windows siano configurati. Per altre informazioni sulla configurazione di Active Directory per il supporto della delega, vedere la pagina sull' abilitazione dell'autenticazione delegata.

Nota

Se il client esegue l'autenticazione al servizio front end utilizzando un nome utente e una password corrispondenti a un account di Windows nel servizio back end, il servizio front end può autenticarsi al servizio back end riutilizzando il nome utente e la password del client. Questa è una forma di flusso di identità particolarmente utile in quanto il trasferimento del nome utente e della password al servizio back-end consente a quest'ultimo di eseguire la rappresentazione, ma non costituisce una delega perché Kerberos non viene utilizzato. I controlli di Active Directory sulla delega non vengono applicati all'autenticazione del nome utente e della password.

Capacità di delega come funzione del livello di rappresentazione.

Livello di rappresentazione Il servizio può eseguire la delega tra processi. Il servizio può eseguire la delega tra computer.
Identification No No
Impersonation No
Delegation

Nell'esempio di codice riportato di seguito viene illustrato come utilizzare la delega.

public class HelloService : IHelloService
{
    [OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string Hello(string message)
    {
        WindowsIdentity callerWindowsIdentity = ServiceSecurityContext.Current.WindowsIdentity;
        if (callerWindowsIdentity == null)
        {
            throw new InvalidOperationException
             ("The caller cannot be mapped to a Windows identity.");
        }
        using (callerWindowsIdentity.Impersonate())
        {
            EndpointAddress backendServiceAddress = new EndpointAddress("http://localhost:8000/ChannelApp");
            // Any binding that performs Windows authentication of the client can be used.
            ChannelFactory<IHelloService> channelFactory = new ChannelFactory<IHelloService>(new NetTcpBinding(), backendServiceAddress);
            IHelloService channel = channelFactory.CreateChannel();
            return channel.Hello(message);
        }
    }
}
Public Class HelloService
    Implements IHelloService

    <OperationBehavior(Impersonation:=ImpersonationOption.Required)> _
    Public Function Hello(ByVal message As String) As String Implements IHelloService.Hello
        Dim callerWindowsIdentity As WindowsIdentity = ServiceSecurityContext.Current.WindowsIdentity
        If (callerWindowsIdentity Is Nothing) Then
            Throw New InvalidOperationException("The caller cannot be mapped to a Windows identity.")
        End If

        Dim backendServiceAddress As EndpointAddress = New EndpointAddress("http://localhost:8000/ChannelApp")
        ' Any binding that performs Windows authentication of the client can be used.
        Dim channelFactory As ChannelFactory(Of IHelloService) = _
          New ChannelFactory(Of IHelloService)(New NetTcpBinding(), backendServiceAddress)
        Dim channel As IHelloService = channelFactory.CreateChannel()
        Return channel.Hello(message)
    End Function
End Class

Procedura: configurare un'applicazione per utilizzare una delega vincolata.

Prima di utilizzare una delega vincolata, è necessario che il mittente, il destinatario e il controller di dominio siano configurati per raggiungere tale obiettivo. La procedura riportata di seguito elenca i passaggi che consentono la delega vincolata. Per altre informazioni sulle differenze tra la delega e la delega vincolata, vedere la parte che descrive gli argomenti vincolati nella pagina sulle estensioni Kerberos di Windows Server 2003 .

  1. Nel controller di dominio, cancellare la casella di controllo L'account è sensibile e non può essere delegato selezionata per l'account nel quale viene eseguita l'applicazione del client.

  2. Nel controller di dominio, selezionare la casella di controllo L'account è attendibile per la delega selezionata per l'account nel quale viene eseguita l'applicazione del client.

  3. Nel controller di dominio, configurare il computer di livello intermedio in modo che sia attendibile per la delega facendo clic sull'opzione Computer attendibili per la delega .

  4. Nel controller di dominio, configurare il computer di livello intermedio per l'utilizzo della delega vincolata facendo clic sull'opzione Computer attendibili per la delega solo ai servizi specificati .

Per istruzioni più dettagliate sulla configurazione della delega vincolata, vedere Transizione del protocollo Kerberos e delega vincolata.

Vedi anche