Dela via


Delegering och personifiering med WCF

Personifiering är en vanlig teknik som tjänster använder för att begränsa klientåtkomsten till en tjänstdomäns resurser. Tjänstdomänresurser kan antingen vara datorresurser, till exempel lokala filer (personifiering) eller en resurs på en annan dator, till exempel en filresurs (delegering). Ett exempelprogram finns i Personifiera klienten. Ett exempel på hur du använder personifiering finns i Så här: Personifiera en klient på en tjänst.

Viktigt!

Tänk på att när du personifierar en klient på en tjänst körs tjänsten med klientens autentiseringsuppgifter, som kan ha högre behörighet än serverprocessen.

Översikt

Klienter anropar vanligtvis en tjänst för att låta tjänsten utföra vissa åtgärder för klientens räkning. Med personifiering kan tjänsten fungera som klient när åtgärden utförs. Med delegering kan en klientdelstjänst vidarebefordra klientens begäran till en serverdelstjänst på ett sådant sätt att serverdelstjänsten också kan personifiera klienten. Personifiering används oftast som ett sätt att kontrollera om en klient har behörighet att utföra en viss åtgärd, medan delegering är ett sätt att flöda personifieringsfunktioner, tillsammans med klientens identitet, till en serverdelstjänst. Delegering är en Windows-domänfunktion som kan användas när Kerberos-baserad autentisering utförs. Delegering skiljer sig från identitetsflödet och eftersom delegering överför möjligheten att personifiera klienten utan innehav av klientens lösenord är det en mycket högre privilegierad åtgärd än identitetsflödet.

Både personifiering och delegering kräver att klienten har en Windows-identitet. Om en klient inte har en Windows-identitet är det enda tillgängliga alternativet att skicka klientens identitet till den andra tjänsten.

Grunderna för personifiering

Windows Communication Foundation (WCF) stöder personifiering för en mängd olika klientautentiseringsuppgifter. I det här avsnittet beskrivs stöd för tjänstmodell för att personifiera anroparen under implementeringen av en tjänstmetod. Här beskrivs också vanliga distributionsscenarier som omfattar personifiering och SOAP-säkerhet och WCF-alternativ i dessa scenarier.

Det här avsnittet fokuserar på personifiering och delegering i WCF när du använder SOAP-säkerhet. Du kan också använda personifiering och delegering med WCF när du använder transportsäkerhet, enligt beskrivningen i Använda personifiering med transportsäkerhet.

Två metoder

WCF SOAP-säkerhet har två olika metoder för att utföra personifiering. Vilken metod som används beror på bindningen. Den ena är personifiering från en Windows-token som hämtats från SSPI (Security Support Provider Interface) eller Kerberos-autentisering, som sedan cachelagras på tjänsten. Den andra är personifiering från en Windows-token som hämtats från Kerberos-tilläggen, som tillsammans kallas Service-for-User (S4U).

Cachelagrad tokenpersonifiering

Du kan utföra cachelagrad token-personifiering med följande:

S4U-baserad personifiering

Du kan utföra S4U-baserad personifiering med följande:

  • WSHttpBinding, WSDualHttpBinding, och NetTcpBinding med en certifikatklientautentiseringsuppgift som tjänsten kan mappa till ett giltigt Windows-konto.

  • Alla CustomBinding som använder en Windows-klientautentiseringsuppgift med egenskapen inställd på falserequireCancellation .

  • Alla CustomBinding som använder ett användarnamn eller Windows-klientautentiseringsuppgifter och säker konversation med egenskapen inställd på requireCancellationfalse.

I vilken utsträckning tjänsten kan personifiera klienten beror på vilka privilegier tjänstkontot har när det försöker personifiera, vilken typ av personifiering som används och eventuellt omfattningen av personifiering som klienten tillåter.

Kommentar

När klienten och tjänsten körs på samma dator och klienten körs under ett systemkonto (till exempel Local System eller Network Service) kan klienten inte personifieras när en säker session upprättas med tillståndskänsliga säkerhetskontexttoken. Ett Windows-formulär- eller konsolprogram körs vanligtvis under det inloggade kontot, så att kontot kan personifieras som standard. Men när klienten är en ASP.NET sida och den sidan finns i IIS 6.0 eller IIS 7.0 körs klienten som standard under Network Service kontot. Alla bindningar som tillhandahålls av systemet som stöder säkra sessioner använder som standard en tillståndslös säkerhetskontexttoken (SCT). Men om klienten är en ASP.NET sida och säkra sessioner med tillståndskänsliga SCT används kan klienten inte personifieras. Mer information om hur du använder tillståndskänsliga SCT i en säker session finns i Så här skapar du en säkerhetskontexttoken för en säker session.

Personifiering i en tjänstmetod: Deklarativ modell

De flesta personifieringsscenarier omfattar körning av tjänstmetoden i anroparkontexten. WCF tillhandahåller en personifieringsfunktion som gör det enkelt att göra det genom att tillåta användaren att ange personifieringskravet OperationBehaviorAttribute i attributet. I följande kod personifierar till exempel WCF-infrastrukturen anroparen innan metoden körs Hello . Alla försök att komma åt interna resurser i Hello metoden lyckas endast om åtkomstkontrollistan (ACL) för resursen tillåter anroparens åtkomstbehörighet. Om du vill aktivera personifiering anger du Impersonation egenskapen till ett av ImpersonationOption uppräkningsvärdena, antingen ImpersonationOption.Required eller ImpersonationOption.Allowed, enligt följande exempel.

Kommentar

När en tjänst har högre autentiseringsuppgifter än fjärrklienten används autentiseringsuppgifterna för tjänsten om Impersonation egenskapen är inställd på Allowed. Om en lågprivilegierad användare tillhandahåller sina autentiseringsuppgifter kör en tjänst med högre privilegier metoden med tjänstens autentiseringsuppgifter och kan använda resurser som den lågprivilegierade användaren annars inte skulle kunna använda.

[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

WCF-infrastrukturen kan endast personifiera anroparen om anroparen autentiseras med autentiseringsuppgifter som kan mappas till ett Windows-användarkonto. Om tjänsten är konfigurerad för att autentisera med en autentiseringsuppgift som inte kan mappas till ett Windows-konto körs inte tjänstmetoden.

Kommentar

I Windows XP misslyckas personifieringen om en tillståndskänslig SCT skapas, vilket resulterar i en InvalidOperationException. Mer information finns i Scenarier som inte stöds.

Personifiering i en tjänstmetod: Imperativ modell

Ibland behöver en anropare inte personifiera hela tjänstmetoden för att fungera, utan bara för en del av den. I det här fallet hämtar du Windows-identiteten för anroparen i tjänstmetoden och utför imperativt personifieringen. Gör detta genom att använda WindowsIdentity egenskapen ServiceSecurityContext för för att returnera en instans av WindowsIdentity klassen och anropa Impersonate metoden innan du använder instansen.

Kommentar

Se till att använda Visual Basic-instruktionenUsing eller C#- using instruktionen för att automatiskt återställa personifieringsåtgärden. Om du inte använder -instruktionen, eller om du använder ett annat programmeringsspråk än Visual Basic eller C#, måste du återställa personifieringsnivån. Om du inte gör det kan det utgöra grunden för överbelastningsattacker och utökade privilegier.

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

Personifiering för alla tjänstmetoder

I vissa fall måste du utföra alla metoder för en tjänst i anroparens kontext. I stället för att uttryckligen aktivera den här funktionen per metod använder du ServiceAuthorizationBehavior. Som du ser i följande kod anger du ImpersonateCallerForAllOperations egenskapen till true. ServiceAuthorizationBehavior hämtas från samlingar av beteenden i ServiceHost klassen. Observera också att egenskapen Impersonation för den OperationBehaviorAttribute som tillämpas på varje metod också måste anges till antingen Allowed eller 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

I följande tabell beskrivs WCF-beteendet för alla möjliga kombinationer av ImpersonationOption och ImpersonateCallerForAllServiceOperations.

ImpersonationOption ImpersonateCallerForAllServiceOperations Funktionssätt
Obligatoriskt saknas WCF personifierar anroparen
Tillåtet falskt WCF personifierar inte anroparen
Tillåtet true WCF personifierar anroparen
NotAllowed falskt WCF personifierar inte anroparen
NotAllowed true Otillåtna. (En InvalidOperationException utlöses.)

Personifieringsnivå som hämtas från Windows-autentiseringsuppgifter och cachelagrad tokenpersonifiering

I vissa scenarier har klienten partiell kontroll över den personifieringsnivå som tjänsten utför när en Windows-klientautentiseringsuppgift används. Ett scenario inträffar när klienten anger en nivå för anonym personifiering. Det andra inträffar när personifiering utförs med en cachelagrad token. Detta görs genom att ange AllowedImpersonationLevel egenskapen för WindowsClientCredential klassen, som används som en egenskap för den generiska ChannelFactory<TChannel> klassen.

Kommentar

Om du anger en personifieringsnivå för Anonym kan klienten logga in anonymt på tjänsten. Tjänsten måste därför tillåta anonym inloggning, oavsett om personifiering utförs.

Klienten kan ange personifieringsnivån som Anonymous, Identification, Impersonationeller Delegation. Endast en token på den angivna nivån skapas, enligt följande kod.

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

I följande tabell anges personifieringsnivån som tjänsten hämtar när den personifierar från en cachelagrad token.

AllowedImpersonationLevel Värde Tjänsten har SeImpersonatePrivilege Tjänsten och klienten kan delegering Cachelagrad token ImpersonationLevel
Anonym Ja saknas Personifiering
Anonym Nej saknas Identifiering
Identifiering saknas saknas Identifiering
Personifiering Ja saknas Personifiering
Personifiering Nej saknas Identifiering
Delegering Ja Ja Delegering
Delegering Ja Nej Personifiering
Delegering Nej saknas Identifiering

Personifieringsnivå som hämtas från autentiseringsuppgifter för användarnamn och cachelagrad tokenpersonifiering

Genom att skicka tjänstens användarnamn och lösenord gör en klient det möjligt för WCF att logga in som den användaren, vilket motsvarar att ställa in AllowedImpersonationLevel egenskapen på Delegation. (Är AllowedImpersonationLevel tillgängligt för klasserna WindowsClientCredential och HttpDigestClientCredential .) Följande tabell innehåller personifieringsnivån som erhålls när tjänsten tar emot autentiseringsuppgifter för användarnamn.

AllowedImpersonationLevel Tjänsten har SeImpersonatePrivilege Tjänsten och klienten kan delegering Cachelagrad token ImpersonationLevel
saknas Ja Ja Delegering
saknas Ja Nej Personifiering
saknas Nej saknas Identifiering

Personifieringsnivå som hämtats från S4U-baserad personifiering

Tjänsten har SeTcbPrivilege Tjänsten har SeImpersonatePrivilege Tjänsten och klienten kan delegering Cachelagrad token ImpersonationLevel
Ja Ja saknas Personifiering
Ja Nej saknas Identifiering
Nej n/a saknas Identifiering

Mappa ett klientcertifikat till ett Windows-konto

Det är möjligt för en klient att autentisera sig själv till en tjänst med hjälp av ett certifikat och låta tjänsten mappa klienten till ett befintligt konto via Active Directory. Följande XML visar hur du konfigurerar tjänsten för att mappa certifikatet.

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

Följande kod visar hur du konfigurerar tjänsten.

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

Delegering

För att delegera till en serverdelstjänst måste en tjänst utföra Kerberos multi-leg (SSPI utan NTLM-återställning) eller Kerberos direktautentisering till serverdelstjänsten med hjälp av klientens Windows-identitet. Om du vill delegera till en serverdelstjänst skapar du en ChannelFactory<TChannel> och en kanal och kommunicerar sedan via kanalen medan du personifierar klienten. Med den här formen av delegering beror avståndet där serverdelstjänsten kan finnas från klientdelstjänsten på personifieringsnivån som uppnås av klientdelstjänsten. När personifieringsnivån är Impersonationmåste klientdels- och serverdelstjänsterna köras på samma dator. När personifieringsnivån är Delegationkan klientdels- och serverdelstjänsterna finnas på separata datorer eller på samma dator. Aktivering av personifiering på delegeringsnivå kräver att Windows-domänprincipen konfigureras för att tillåta delegering. Mer information om hur du konfigurerar Active Directory för delegeringsstöd finns i Aktivera delegerad autentisering.

Kommentar

När en klient autentiserar till klientdelstjänsten med ett användarnamn och lösenord som motsvarar ett Windows-konto på serverdelstjänsten, kan klientdelstjänsten autentisera till serverdelstjänsten genom att återanvända klientens användarnamn och lösenord. Detta är en särskilt kraftfull form av identitetsflöde, eftersom överföring av användarnamn och lösenord till serverdelstjänsten gör att serverdelstjänsten kan utföra personifiering, men den utgör inte delegering eftersom Kerberos inte används. Active Directory-kontroller vid delegering gäller inte för användarnamn och lösenordsautentisering.

Delegeringsförmågan som en funktion på personifieringsnivå

Personifieringsnivå Tjänsten kan utföra delegering mellan processer Tjänsten kan utföra delegering mellan datorer
Identification Nej No
Impersonation Ja No
Delegation Ja Ja

Följande kodexempel visar hur du använder delegering.

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

Så här konfigurerar du ett program för att använda begränsad delegering

Innan du kan använda begränsad delegering måste avsändaren, mottagaren och domänkontrollanten konfigureras för att göra det. I följande procedur visas de steg som aktiverar begränsad delegering. Mer information om skillnaderna mellan delegering och begränsad delegering finns i den del av Windows Server 2003 Kerberos-tillägg som diskuterar begränsad diskussion.

  1. På domänkontrollanten avmarkerar du kryssrutan Konto är känsligt och kan inte delegeras för det konto som klientprogrammet körs under.

  2. På domänkontrollanten markerar du kryssrutan Konto är betrott för delegering för det konto som klientprogrammet körs under.

  3. På domänkontrollanten konfigurerar du mellannivådatorn så att den är betrodd för delegering genom att klicka på alternativet Betrodd dator för delegering .

  4. På domänkontrollanten konfigurerar du mellannivådatorn så att den använder begränsad delegering genom att klicka på alternativet Lita på den här datorn för delegering till angivna tjänster .

Mer detaljerade anvisningar om hur du konfigurerar begränsad delegering finns i Kerberos-protokollövergång och begränsad delegering.

Se även