Anspruchsbasierte Anwendungen

Anspruchsbasierte Autorisierung mit WIF

Michele Leroux Leroux

Beispielcode herunterladen.

In den letzten Jahren wurden verbundene Sicherheitsmodelle und anspruchsbasierte Zugriffssteuerung zunehmend beliebter. In einem verbundenen Sicherheitsmodell kann Authentifizierung durch einen Sicherheitstokendienst (Security Token Service, STS) erfolgen; der STS kann Sicherheitstoken ausstellen, die Ansprüche (Claims) enthalten, die die Identität des authentifizierten Benutzers sowie die Zugriffsrechte des Benutzers bestätigen. Der Verbund ermöglicht Benutzern, sich in ihrer eigenen Domäne zu identifizieren und dadurch Zugriff auf Anwendungen und Dienste aus anderen Domänen zu erhalten, vorausgesetzt, dass die Domänen eine eingerichtete Vertrauensstellung haben. Durch diese Vorgehensweise ist es nicht mehr nötig, doppelte Konten für einen Benutzer bereitzustellen und zu verwalten, und es werden SSO-Szenarios mit einmaliger Anmeldung möglich. Anspruchsbasierter Zugriff ist für das verbundene Sicherheitsmodell unverzichtbar, wobei Anwendungen und Dienste den Zugriff auf Merkmale und Funktionen in vertrauenswürdigen Domänen basierend auf den Ansprüchen vom Aussteller (dem STS) autorisieren. Ansprüche können Informationen über den Benutzer, Rollen oder Berechtigungen enthalten, sodass ein äußerst flexibles Autorisierungsmodell geboten wird. Zusammen ermöglichen Verbundsicherheit und anspruchsbasierter Zugriff eine Reihe von Integrationsszenarios über mehrere Anwendungen, Abteilungen und Partner in einem weit gefassten Vernetzungssystem hinweg.

 Inzwischen gibt es in diesem Bereich auch gut entwickelte Plattformtools. WIF (Windows Identity Foundation) ist ein umfangreiches Identitätsmodellframework für die Erstellung anspruchsbasierter Anwendungen und Dienste sowie die Unterstützung von Szenarios mit aktiver und passiver verbundener Sicherheit. Mit WIF können Sie passiven Verbund für ASP.NET-Anwendungen aktivieren und mühelos ein anspruchsbasiertes Autorisierungsmodell in die ASP.NET-Anwendungen und WCF-Dienste integrieren. Darüber hinaus stellt WIF die Grundlagen zum Erstellen von benutzerdefinierten STS-Implementierungen bereit und enthält Funktionen und Steuerelemente zur Unterstützung von Authentifizierungsszenarios, die verwaltete Informationskarten und Identitätsauswahlen wie z. B. Windows CardSpace einbeziehen. 

WIF reduziert deutlich den erforderlichen Code zur Implementierung von funktionsreichen Anwendungsszenarios, die auf verbundener und anspruchsbasierter Sicherheit beruhen. In diesem zweiteiligen Artikel konzentriere ich mich auf die Framework-Kernfunktionalität zur Aktivierung des passiven Verbunds für ASP.NET-Anwendungen und zur Unterstützung von anspruchsbasierten Sicherheitsmodellen in WCF and ASP.NET. In diesem Artikel geht es hauptsächlich um WCF; ASP.NET folgt in einem späteren Artikel.

Warum Verbund- und anspruchsbasierte Sicherheit?

Die Vorteile von Verbund- und anspruchsbasierter Sicherheit sollten im Kontext verschiedener Ziele gesehen werden:

  • Entkopplung des Authentifizierungsmechanismus von Anwendungen und Diensten.
  • Ersetzen von Rollen durch Ansprüche als flexibleres, fein abstimmbares Produkt für die Autorisierung.
  • Reduzierung von IT-Problemen beim Bereitstellen und Deaktivieren von Benutzerkonten.
  • Erteilen von Zugriffsrechten auf Anwendungsmerkmale und -funktionen für vertrauenswürdige Domänen, einschließlich externe Verbundpartner.

Wenn auch nur eins dieser Ziele auf Ihr Anwendungsszenario zutrifft, kann die Einführung eines anspruchsbasierten Modells, das umgehend oder später Verbundsicherheit nach sich zieht, unglaublich hilfreich sein.

Wenn Sie Ihre Anwendungen und Dienste entwerfen, sind das Authentifizierungs- und Autorisierungsmodell Teil dieses Entwurfs. Beispielsweise wird in einer Intranetanwendung normalerweise erwartet, dass sich Benutzer mit ihren Windows-Anmeldedaten bei einer bestimmten Domäne authentifizieren, während bei einer Internetanwendung in der Regel ein angepasster Anmeldeinformationsspeicher wie Microsoft SQL Server verwendet wird. Anwendungen können auch Zertifikate oder Smartcard-Authentifizierung erfordern oder mehrere Anmeldetypen unterstützen, damit verschiedene Benutzergruppen den jeweils passenden Typ verwenden können. Wenn sich Benutzer in Ihrer Anwendung ausschließlich (und immer) mit einem Anmeldetyp authentifizieren müssen, haben Sie einen leichten Job. Meistens entwickeln sich jedoch die von einer Anwendung unterstützten Anmeldetypen weiter, um alternative oder zusätzliche Authentifizierungsmodi für andere Benutzergruppen zu unterstützen.

Beispielsweise kann eine Anwendung interne Benutzer hinter der Firewall innerhalb einer Domäne und gleichzeitig externe Benutzer übers Internet unterstützen. Wenn das Sicherheitsmodell für eine Anwendung vom Authentifizierungsmodus abgekoppelt wird – wie es beim anspruchsbasierten Modell der Fall ist – hat es kaum Auswirkungen auf die Anwendung, wenn Sie neue Authentifizierungsmodi einführen.

Auf ähnliche Weise sind Anwendungen flexibler, wenn die Autorisierung nicht an einen festen Rollensatz gebunden ist. Wenn Ihre Anwendung bei der Zugriffsautorisierung immer auf einen bestimmten Rollensatz zurückgreift und diese Rollen immer dieselben Zugriffsrechte auf Merkmale und Funktionen mit sich bringen, sind Sie wieder auf der sicheren Seite. Doch die Bedeutung von Rollen ist häufig in verschiedenen Abteilungen, die eine Anwendung verwenden, unterschiedlich, und macht eine Anpassung erforderlich. Das kann heißen, dass Rollen je nach Benutzerdomäne unterschiedlich bewertet werden oder für die Steuerung der Zugriffsrechte benutzerdefinierte Rollen erstellt werden. WIF macht die Übernahme eines anspruchsbasierten Sicherheitsmodells ganz einfach, sodass Sie Rollen bei Bedarf vom Autorisierungsmechanismus abkoppeln können. Auf diese Weise können logische Rollen einer besser abgestimmten Anspruchsgruppe zugewiesen werden und die Anwendung autorisiert den Zugriff basierend auf diesen Ansprüchen. Wenn geänderte oder neue Rollen eine neue Anspruchsgruppe erfordern, hat dies keine Auswirkungen auf die Anwendung.

Natürlich können Ansprüche noch viel mehr als nur Rollen oder Berechtigungen sein. Einer der zusätzlichen Vorteile bei der Verwendung von anspruchsbasierten Modellen ist, dass ein Anspruch Informationen über einen authentifizierten Benutzer wie E-Mail-Adresse, vollständiger Name, Geburtsdatum usw. enthalten kann. Ansprüche können auch verwendet werden, um Informationen zu verifizieren, ohne das tatsächliche Alter oder Geburtsdatum des Benutzers bekannt zu geben (eine Information, die viele Benutzer nicht in der Öffentlichkeit verbreiten möchten). Der Anspruch kann beispielsweise angeben, ob ein Benutzer das Mindestalter für eine bestimmte Aktion hat (durch eine Booleschen Angabe, ob das Alter über 13 oder 21 liegt).

Obwohl die Entkopplung des Authentifizierungsmechanismus und bestimmter Rollen von Anwendungen und Diensten Änderungen erleichtert, ist das anspruchsbasierte Modell auch für verbundene Sicherheitsszenarios unverzichtbar, die das Gewähren von Zugriffsrechten für Benutzer, die einer vertrauenswürdigen Domäne angehören, stark vereinfacht. Der Verbund reduziert den IT-Verwaltungsaufwand und einige der Risiken, die bei der Identitätsverwaltung auftreten. Benutzeranmeldeinformationen müssen nicht mehr für mehrere Anwendungen oder Domänen verwaltet werden; dies verringert wiederum Probleme beim Bereitstellen und Deaktivieren von Konten für mehrere Domänen (z. B. das Versäumnis, ein Konto an mehreren Standorten zu löschen). Die Kennwortsynchronisierung bei der Verwaltung mehrerer Konten ist dann ebenfalls kein Problem mehr. Der Verbund ermöglicht außerdem SSO-Szenarios, da sich Benutzer bei einer Anwendung anmelden können und damit gleichzeitig Zugriff auf eine andere Anwendung erhalten (möglicherweise sogar über mehrere Sicherheitsdomänen hinweg), ohne sich erneut authentifizieren zu müssen. Schließlich ist das Hinzufügen neuer Vertrauensstellungen zwischen Domänen mit Verbundsicherheitsplattformen wie Active Directory-Verbunddienste (ADFS) und WIF ebenfalls einfacher. Auf diese Weise wird die Erweiterung einer Anwendung auf zusätzliche Domänen innerhalb eines Unternehmensbereichs oder sogar auf externe Partnerdomänen rationalisiert.

Aktiver Verbund mit WIF

Aktive Verbundszenarios basieren auf dem WS-Federation Active Requestor Profile (siehe WS-Federation TC unter oasis-open.org/committees/tc_home.php?wg_abbrev=wsfed) und der WS-Trust-Spezifikation (siehe WS-Trust 1.3 unter docs.oasis-open.org/ws-sx/ws-trust/200512/ws-trust-1.3-os.html). WS-Trust beschreibt auf allgemeiner Ebene einen Vertrag mit vier Dienstvorgängen: Ausstellen, Überprüfen, Erneuern und Stornieren. Dementsprechend werden diese Vorgänge von Clients zur Anforderung eines Sicherheitstokens, zum Überprüfen eines Sicherheitstokens, zum Erneuern eines abgelaufenen Sicherheitstokens und zum Stornieren eines Sicherheitstokens, das nicht mehr verwendet werden darf, aufgerufen. Jeder Vorgang verarbeitet Nachrichten zur Anforderung eines Sicherheitstokens (Request for Security Token; RST) und sendet Antworten in Form einer RST-Antwort (RSTR) entsprechend der WS-Trust-Spezifikation. Diese WS-Trust-Funktionen werden durch einen STS (oder Tokenaussteller) implementiert, ein wichtiger Teilnehmer in jedem Verbundsicherheitsszenario.

Ein einfaches aktives Verbundszenario ist in Abbildung 1 veranschaulicht. Dieses Szenario beinhaltet eine Windows-Clientanwendung (der Anforderer), einen WCF-Dienst (Relying Party oder RP) und einen STS, der zur RP-Domäne gehört (RP-STS). Wie die Abbildung zeigt, verwendet der Client einen WCF-Proxy, um zuerst die Authentifizierung mit dem RP-STS zu koordinieren, dann ein Sicherheitstoken anzufordern und schließlich RP aufzurufen und dabei das ausgestellte Sicherheitstoken mit der Anforderung zu übergeben.


Abbildung 1 Einfaches aktives Verbundszenario

In diesem Szenario ist RP-STS auch der Identitätsprovider (IdP) für Benutzer, die sich bei der RP-Domäne authentifizieren. Das heißt, dass der RP-STS für die Authentifizierung der Benutzer verantwortlich ist, die Identität dieser Benutzer bestätigt und die für die RP-Autorisierung relevanten Ansprüche ausgibt. Die RP überprüft, ob das Sicherheitstoken vom RP-STS ausgestellt wurde, und autorisiert den Zugriff basierend auf den ausgestellten Ansprüchen.

Ich habe eine Aufgabenlistenanwendung (TodoList) erstellt, um die Implementierungserörterung für dieses Szenario zu erleichtern. Das zugehörige Codebeispiel umfasst einen WPF-Client, einen WCF-Dienst und einen aktiven, mit WIF implementierten STS. Für den weiteren Kontext implementiert der WCF-Dienst (TodoListService) den Vertrag (ITodoListService), wie in Abbildung 2 gezeigt. Der Client ruft den Dienst über einen WCF-Proxy auf, um alle Todo-Elemente abzurufen und um Elemente hinzuzufügen, zu aktualisieren oder zu löschen. "TodoListService" beruht auf dem Erstellen, Lesen, Aktualisieren und Löschen von Ansprüchen, um Zugriff auf seine Vorgänge zu gewähren.

Abbildung 2 ITodoListService-Definition

[ServiceContract(Namespace="urn:TodoListApp/2009/06")]
public interface ITodoListService
{
    [OperationContract]
    List<TodoItem> GetItems();
    [OperationContract]
    string CreateItem(TodoItem item);
    [OperationContract]
    void UpdateItem(TodoItem item);
    [OperationContract]
    void DeleteItem(string id);
}

Zur Implementierung dieses aktiven Verbundszenarios befolgen Sie diese vier Schritte:

  1. Verbundsicherheits-WCF-Endpunkt für TodoListService zur Verfügung stellen
  2. WCF-Proxy für Clientanwendung erstellen und Proxy mit Anmeldeinformationen zur Authentifizierung beim RP-STS initialisieren
  3. WIF für TodoListService aktivieren, um anspruchsbasierte Autorisierung zu ermöglichen
  4. Berechtigungsanforderungen (IsInRole) oder andere Autorisierungsprüfungen platzieren, um den Zugriff auf Dienstvorgänge oder andere Funktionen zu steuern

Diese Schritte werden in den folgenden Abschnitten näher erläutert.

Verfügbarmachen von Verbund-Endpunkten

Anspruchsbasierte WCF-Dienste stellen normalerweise Verbund-Endpunkte zur Verfügung, die ausgestellte Token empfangen, die z. B. auf dem SAML-Standard basieren. WCF stellt zwei Bindungen zur Unterstützung von Verbundsicherheitsszenarios mit WS-Trust bereit. WSFederationHttpBinding ist die ursprüngliche Standardbindung, die auf WS-Trust 2005 basiert (einer älteren Version des Protokolls). WS2007FederationHttpBinding ist die neueste Version der Bindung (veröffentlicht mit Microsoft .NET Framework 3.5). Sie unterstützt WS-Trust 1.3, den genehmigten Standard. In der Regel sollten Sie WS2007FederationHttpBinding verwenden, es sei denn, die Interoperabilität erfordert die Verwendung der älteren Version. Ein STS basierend auf den ADFS Version 2 oder WIF kann beide Versionen von WS-Trust unterstützen.

Wenn Sie einen Verbund-Endpunkt für einen Dienst zur Verfügung stellen, geben Sie normalerweise Informationen über das erwartete Sicherheitstoken-Format, die erforderlichen und optionalen Anspruchstypen sowie den vertrauenswürdigen Tokenaussteller an. Abbildung 3 zeigt die Auflistung "system.serviceModel" für TodoListService, der einen einzigen Verbund-Endpunkt über WS2007FederationHttpBinding zur Verfügung stellt.

Abbildung 3 Von TodoListService zur Verfügung gestellter Verbund-Endpunkt

<system.serviceModel>
  <services>
    <service name="TodoList.TodoListService" 
behaviorConfiguration="serviceBehavior">
      <endpoint address="" binding="ws2007FederationHttpBinding" bindingConfiguration="wsFed" contract="Contracts.ITodoListService" />
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      <host>
        <baseAddresses>
          <add baseAddress="http://localhost:8000/TodoListService"/>
        </baseAddresses>
      </host>
    </service>
  </services>
  <bindings>
    <ws2007FederationHttpBinding>
      <binding name="wsFed">
        <security mode="Message" issuedTokenType=
“http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-.1#SAMLV1.1" issuedKeyType="SymmetricKey" negotiateServiceCredential="true">
          <message>
            <claimTypeRequirements>
              <add claimType= 
“https://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" isOptional="false"/>
              <add claimType= "urn:TodoListApp/2009/06/claims/permission" 
isOptional="false"/>
            </claimTypeRequirements>
            <issuerMetadata address="http://localhost:8010/rpsts/mex" />
          </message>
        </security>
      </binding>
    </ws2007FederationHttpBinding>
  </bindings>
  <behaviors>
    <serviceBehaviors>
      <behavior name="serviceBehavior">
        <serviceMetadata/>
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

Verbundsicherheitsszenarios stützen sich normalerweise auf SAML-Token, doch dies ist nicht zwingend notwendig. Für dieses Szenario werden SAML 1.1-Token verwendet, wie vom issuedTokenType-URI angegeben (docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0.pdf). Für alternative Tokentypen wie SAML 1.0 oder SAML 2.0 verwenden Sie den URI für den jeweiligen Standard.  Natürlich muss der in der verbundenen Bindungskonfiguration angegebene STS den angeforderten Tokentyp unterstützen.

Weitere relevante Einstellungen im Nachrichtenabschnitt sind "issuedKeyType" und "negotiateServiceCredential". Die Einstellung "issuedKeyType" gibt an, ob der Schlüssel (siehe blogs.msdn.com/vbertocci/archive/2008/01/02/on-prooftokens.aspx) symmetrisch (Standard) oder asymmetrisch (erfordert größeren Aufwand) ist. Auch diese Einstellung muss mit dem STS kompatibel sein. Wenn "negotiateServiceCredential" (Dienstanmeldeinformationen aushandeln) auf "true" gesetzt ist, muss der Client den Zugriff auf den öffentlichen RP-Schlüssel nicht im Voraus festlegen, aber Aushandlung ist kein interoperables Protokoll. Falls der Client kein WCF-Client ist, sollten Sie "negotiateServiceCredential" auf "false" setzen. Aber keine Sorge. Wenn er auf "false" gesetzt ist, liefert die Proxygenerierung mit SvcUtil dem Client eine base64-codierte Kopie des öffentlichen RP-Schlüssels.

Die im Abschnitt "claimTypeRequirements" bereitgestellten Anspruchstypen geben die erforderlichen und optionalen Anspruchstypen an, die der Dienst für die Autorisierung benötigt. In diesem Fall erwartet der Dienst einen Namensanspruch zur Identifikation des Benutzers und mindestens einen Berechtigungsanspruch; ein benutzerdefinierter Anspruchstyp, der das Recht des Benutzers zum Erstellen, Lesen, Aktualisieren und Löschen von Todo-Elementen angibt. (Diese Anspruchstypen sind weiter unten in Abbildung 4 aufgeführt.) Die Liste der Anspruchstypen ist in den Metadaten des Dienstes enthalten, sodass Clients diese Informationen in das RST aufnehmen können. Häufig kennt der STS die Ansprüche, die er für eine bestimmte RP ausstellt, was bedeutet, dass die Liste für die Verbund-Bindung nicht allumfassend sein muss.

Abbildung 4 Pro Benutzer ausgestellte Ansprüche für das TodoList-Anwendungsszenario

Der vertrauenswürdige Tokenaussteller für dieses Szenario ist RP-STS, der mit WIF implementiert wurde. RP-STS stellt einen einzelnen WS-Trust-Endpunkt unter http://localhost:8010/rpsts zur Verfügung, und seine Metadatenaustausch-Adresse ist http://localhost:8010/rpsts/mex. In Abbildung 3 wird die Metadatenadresse des Ausstellers im Abschnitt "issuerMetadata" angegeben, sodass der Client bei der Proxygenerierung die verfügbaren STS-Endpunkte ermitteln kann.

Angenommen, der STS stellt mehrere Endpunkte zur Verfügung, z. B. zur Authentifizierung von Intranetbenutzern mit Windows-Anmeldeinformationen unter http://localhost:8010/rpsts/internal und zur Authentifizierung von Internetbenutzern mit Benutzername und Kennwort unter http://localhost:8010/rpsts/external. Der RP-Dienst kann optional festlegen, dass ein bestimmter Ausstellerendpunkt mit seiner Verbund-Endpunktkonfiguration verknüpft wird, sodass bei der Proxygenerierung eines Clients die Konfiguration zur Kommunikation mit dem STS diesen Endpunkt statt des ersten kompatiblen Endpunkts verwendet. Geben Sie dazu eine Adresse für "issuerMetadata" sowie für die Ausstellerelemente wie folgt an:

<issuerMetadata address="http://localhost:8010/rpsts/mex" />
<issuer address="http://localhost:8010/rpsts/mex/external" />

Der Vorteil dieser Vorgehensweise besteht darin, dass die Proxygenerierung für Clients vereinfacht wird, wenn mehrere STS-Endpunkte zur Auswahl stehen und die RP beeinflussen möchte, welcher verwendet wird. Falls es der RP egal ist, bei welchem Endpunkt sich der Client authentifiziert, sollten Sie nur die Einstellung "issuerMetadata" angeben und die Clientanwendung den geeigneten Endpunkt für die Authentifizierung bestimmen lassen.

Beachten Sie Folgendes: Wenn die Dienstkonfiguration das Element "issuerMetadata" auslässt und nur die Ausstelleradresse angibt, sollte die Adresse die logische URI des Ausstellers (http://localhost:8010/rpsts/issuer) auswerten, die nicht unbedingt auf eine physische STS-Endpunktadresse verweisen muss. Bei einer gleichwertigen Konfiguration beim Client wird der Benutzer aufgefordert, eine verwaltete Informationskarte vom selben Aussteller (über Windows CardSpace) auszuwählen, und die Karte muss ebenfalls den Kriterien des erforderlichen Tokenformats und den Anspruchtstypen entsprechen. Weitere Informationen zu Active-Verbundszenarios mit Windows CardSpace finden Sie unter wpfandcardspace.codeplex.com.

Client-Proxygenerierung

Wenn Sie mit "SvcUtil" oder "Dienstverweis hinzufügen" einen Proxy für einen Windows-Client generieren, wird die Metadatenaustausch-Adresse des Ausstellers verwendet, um Informationen über die vom Aussteller zur Verfügung gestellten Endpunkte zu sammeln. Zur Wiederholung einige mögliche Szenarios:

  • Wenn die Verbund-Bindung für den RP-Dienstendpunkt eine Metadatenaustausch-Adresse ohne genaue Ausstelleradresse bereitstellt, nimmt die Clientkonfiguration den ersten mit dem Protokoll kompatiblen STS-Endpunkt, ohne dem Cliententwickler andere kompatible Endpunkte zur optionalen Verwendung anzuzeigen.
  • Wenn die Verbund-Bindung für den RP-Dienstendpunkt eine Metadatenaustausch-Adresse und eine genaue Ausstelleradresse bereitstellt, nimmt die Clientkonfiguration diese Adresse (vorausgesetzt, sie ist mit dem Protokoll kompatibel).
  • Wenn die Verbund-Bindung für den RP-Dienstendpunkt nur eine Metadatenaustausch-Adresse bereitstellt, nimmt die Clientkonfiguration ebenfalls nur diese Metadatenadresse, ohne Bindungskonfiguration für den Aussteller. Das hat zur Folge, dass eine Identitätsauswahl wie beispielsweise CardSpace aufgerufen wird, wie bereits oben erwähnt.

Angenommen, der Client generiert einen Proxy für "TodoListService", dessen Konfiguration in Abbildung 3 dargestellt ist, und der STS stellt einen einzigen Endpunkt zur Verfügung, dann umfasst die clientseitige Version der "WS2007FederationHttpBinding"-Konfiguration die folgenden Aussteller und "issuerMetadata"-Einstellungen:

<issuer address="http://localhost:8010/rpsts" 
        binding="ws2007HttpBinding" 
        bindingConfiguration="http://localhost:8010/rpsts">
  <identity>
    <certificate encodedValue="[base64 encoded RP-STS certificate]" />
  </identity>
</issuer>
<issuerMetadata address="http://localhost:8010/rpsts/mex" />

Das "issuer"-Element gibt den Ausstellerendpunkt und die erforderliche Bindungskonfiguration für die Kommunikation mit diesem Endpunkt an. In diesem Fall authentifiziert sich der Client mit Benutzernamen und Kennwort mittels Nachrichtensicherheit beim STS, wie in der folgenden "WS2007HttpBinding"-Konfiguration dargestellt ist:

<ws2007HttpBinding>
    <binding name="http://localhost:8010/rpsts" >
        <security mode="Message">
            <message clientCredentialType="UserName" 
                     negotiateServiceCredential="false" 
                     algorithmSuite="Default" 
                     establishSecurityContext="false" />
        </security>
    </binding>
</ws2007HttpBinding>

Der Clientendpunkt verknüpft die Verbund-Bindungskonfiguration mit dem RP-Endpunkt:

<client>
  <endpoint address="http://localhost:8000/TodoListService" 
            binding="ws2007FederationHttpBinding" 
            bindingConfiguration="wsFed"
            contract="TodoList.ITodoListService" name="default">
    <identity>
      <certificate encodedValue="[base64 encoded RP certificate" />
    </identity>
  </endpoint>
</client>

Mit dieser Konfiguration muss der Clientproxy lediglich mit einem gültigen Benutzernamen und Kennwort initialisiert werden, bevor der Dienst aufgerufen wird:

TodoListServiceProxy _Proxy = new TodoListServiceProxy("default");

if (!ShowLogin()) return;

this._Proxy.ClientCredentials.UserName.UserName = this.Username;
this._Proxy.ClientCredentials.UserName.Password = this.Password;
this._TodoItems = this._Proxy.GetItems();

Tokenausstellung

Der Proxy übergibt zuerst die Anmeldeinformationen zur Authentifizierung an den RP-STS und sendet dabei ein RST mit einer Anforderung eines SAML 1.1-Tokens, das angibt, dass die RP mindestens einen Namens- und Berechtigungsanspruch erfordert. Der Benutzer wird anhand des STS-Anmeldeinformationsspeichers authentifiziert, und die entsprechenden Ansprüche werden für den authentifizierten Benutzer ausgestellt. Der Proxy verarbeitet dann die RST-Antwort (RSTR), die das ausgestellte Token enthält, und übergibt dieses Token an die RP zur Herstellung einer sicheren Sitzung für den authentifizierten Benutzer.

Für dieses Beispiel wurde der STS mit WIF erstellt und authentifiziert Benutzer anhand eines angepassten Anmeldeinformationsspeichers; dabei gibt er für jeden Benutzer Ansprüche laut Abbildung 4 aus.

Ein STS, der auf den ADFS Version 2 basiert, authentifiziert Benutzer anhand der Windows-Domäne und gibt Ansprüche entsprechend der ADFS-Konfiguration aus. Ein benutzerdefinierter STS, der auf WIF basiert, kann Benutzer anhand eines Anmeldeinformationsspeichers Ihrer Wahl authentifizieren, Sie müssen jedoch Ihren eigenen Code erstellen, um den Anmeldeinformationsspeicher und den relevanten Anspruchszuordnungsprozess zu verwalten.

 Identitätsmodellkonfiguration

Zur Aktivierung von anspruchsbasierter Autorisierung für Ihre WCF-Dienste mit WIF initialisieren Sie die ServiceHost-Instanz für den Verbund. Sie können dies durch Aufrufen der "ConfigureServiceHost"-Methode programmieren, die vom "FederatedServiceCredentials"-Typ zur Verfügung gestellt wird, wie folgt:

ServiceHost host = new ServiceHost(typeof(TodoList.TodoListService));
FederatedServiceCredentials.ConfigureServiceHost(host);
host.Open();

Dasselbe Ergebnis erreichen Sie deklarativ durch Verwendung der Verhaltenserweiterung "ConfigurationServiceHostBehaviorExtension":

<serviceBehaviors>
  <behavior name="fedBehavior" > 
    <federatedServiceHostConfiguration/>
    <serviceMetadata />
  </behavior>
</serviceBehaviors>

In beiden Fällen wird dem ServiceHost eine Instanz des Typs "FederatedServiceCredentials" zur Steuerung des anspruchsbasierten Autorisierungsverhaltens für den Dienst zugewiesen. Dieser Typ kann entweder durch Programmierung oder durch den Konfigurationsabschnitt "microsoft.identityModel" für den Dienst initialisiert werden. Identitätsmodelleinstellungen gelten speziell für WIF und Bereitstellungseinstellungen für anspruchsbasierte Autorisierung in ASP.NET- und WCF-Anwendungen, von denen die meisten in Abbildung 5 zusammengefasst sind.

Abbildung 5 Zusammenfassung der grundlegenden "microsoft.identityModel"-Elemente

Für WCF-Dienste, die WIF verwenden, müssen Sie "ServiceHost" nicht mehr mit dem typischen WCF-Authentifizierungs- und Autorisierungsverhalten initialisieren. WIF überschreibt dies und bietet eine bessere Möglichkeit zur allgemeinen Sicherheitskonfiguration. (WIF ist auch über anspruchsbasierte und Verbundszenarios hinaus nützlich.) Abbildung 6 enthält die Identitätsmodelleinstellungen für "TodoListService".

Abbildung 6 Häufig für WCF-Dienste bereitgestellte Identitätsmodelleinstellungen

<microsoft.identityModel>
  <service>
    <issuerNameRegistry type="Microsoft.IdentityModel.Tokens.
      ConfigurationBasedIssuerNameRegistry, Microsoft.IdentityModel, 
      Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <trustedIssuers>
        <add name="http://localhost:8010/rpsts" thumbprint=
"c3 95 cd 4a 74 09 a7 77 d4 e3 de 46 d7 08 49 86 76 1a 99 50"/>
      </trustedIssuers>
    </issuerNameRegistry>
    <serviceCertificate>
      <certificateReference findValue="CN=RP" storeLocation="LocalMachine" 
         storeName="My" x509FindType="FindBySubjectDistinguishedName"/>
    </serviceCertificate>
    <audienceUris mode="Always">
      <add value="http://localhost:8000/TodoService"/>
    </audienceUris>
    <certificateValidation certificateValidationMode="PeerTrust" />         
    <securityTokenHandlers>
      <remove type="Microsoft.IdentityModel.Tokens.Saml11.
         Saml11SecurityTokenHandler, Microsoft.IdentityModel, 
         Version=1.0.0.0, Culture=neutral, 
         PublicKeyToken=31bf3856ad364e35"/>
      <add type="Microsoft.IdentityModel.Tokens.Saml11.
         Saml11SecurityTokenHandler, Microsoft.IdentityModel, 
         Version=1.0.0.0, Culture=neutral, 
         PublicKeyToken=31bf3856ad364e35">
        <samlSecurityTokenRequirement >
          <roleClaimType 
            value="urn:TodoListApp/2009/06/claims/permission"/>
        </samlSecurityTokenRequirement>
      </add>
    </securityTokenHandlers>
    <claimsAuthorizationManager 
      type="TodoList.CustomClaimsAuthorizationManager, TodoList"/>
  </service>
</microsoft.identityModel>

Die Einstellung "issuerNameRegistry" dient zur Angabe eines vertrauenswürdigen Zertifikatausstellers. Wenn Sie "ConfigurationBasedIssuerNameRegistry" verwenden, wie in Abbildung 6 gezeigt, müssen Sie eine Liste vertrauenswürdiger Zertifikataussteller bereitstellen, indem Sie deren Fingerabdrücke angeben. Bei der Ausführung überprüft "ConfigurationBasedIssuerNameRegistry" die X509-Sicherheitstoken anhand dieser Liste und lehnt alle ab, deren Fingerabdrücke nicht in der Liste gefunden wurden. Sie können "SimpleIssuerNameRegistry" verwenden, um beliebige X509- oder RSA-Token zuzulassen, aber zweckmäßiger ist es, einen benutzerdefinierten "IssuerNameRegistry"-Typ anzugeben, um Token mit eigener Heuristik zu überprüfen, wenn "ConfigurationBasedIssuerNameRegistry" nicht wie gewünscht funktioniert.

Die Konfiguration in Abbildung 6 lehnt alle Token ab, die nicht vom RP-STS signiert sind (unter Verwendung des Zertifikatsfingerabdrucks für CN=RPSTS). Die folgende Konfiguration gibt stattdessen einen benutzerdefinierten "IssuerNameRegistry"-Typ an, "TrustedIssuerNameRegistry":

<issuerNameRegistry type="TodoListHost.TrustedIssuerNameRegistry, TodoListHost"/>

Die "TrustedIssuerNameRegistry"-Implementierung wird verwendet, um dasselbe Ergebnis zu erhalten – Ablehnung von nicht signierten Token durch CN=RPSTS, indem "SubjectName" des eingehenden Tokens geprüft wird:

public class TrustedIssuerNameRegistry : IssuerNameRegistry
{
    public override string GetIssuerName(SecurityToken securityToken)
    {
        X509SecurityToken x509Token = securityToken as
            X509SecurityToken;
        if (x509Token != null)
        {
            if (String.Equals(x509Token.Certificate.SubjectName.Name,
                "CN=RPSTS"))
            {
                return x509Token.Certificate.SubjectName.Name;
            }
        }

        throw new SecurityTokenException("Untrusted issuer.");
    }
}

Die Einstellung "serviceCertificate" in Abbildung 6 gibt an, welches Zertifikat zur Entschlüsselung eingehender Sicherheitstoken verwendet werden soll, falls sie durch den Aussteller-STS für den RP verschlüsselt wurden. Für die TodoList-Anwendung verschlüsselt RP-STS Token mit dem öffentlichen RP-Schlüssel: CN=RP.

Normalerweise enthält das SAML-Token ein URI-Element "Audience", das angibt, für wen das Token ausgestellt wurde und das vom RP ausgewertet wird. Sie können Token, die nicht für die RP gedacht waren, explizit ablehnen. Standardmäßig ist der "audienceUris"-Modus auf "Always" (Immer) gesetzt, was bedeutet, dass Sie mindestens eine URI für die Überprüfung von eingehenden Token angeben müssen. In Abbildung 6 lässt die Konfiguration nur SAML-Token zu, die eine "AudienceURI" enthalten, die mit der "TodoListService"-Adresse übereinstimmt. Obwohl es allgemein nicht empfohlen wird, können Sie den "audienceUris"-Modus auf "Never" (Nie) setzen, um die Auswertung der Zielgruppen-Einschränkungsbedingung für ein eingehendes SAML-Token zu unterdrücken:

<audienceUris mode="Never"/>

Beachten Sie Folgendes: Wenn der Client ein RST an den STS sendet, schließt er normalerweise eine "AppliesTo"-Einstellung ein, die angibt, für wen das Token ausgestellt werden soll – die RP. Der STS kann diese Informationen zum Ausfüllen der Zielgruppen-URI ("AudienceURI") des SAML-Tokens verwenden.

Die Einstellung "certificateValidation" legt fest, wie eingehende X509-Token (beispielsweise die für die Tokensignatur verwendeten) überprüft werden. In Abbildung 6 ist "certificateValidationMode" auf "PeerTrust" eingestellt, was bedeutet, dass Zertifikate nur dann gültig sind, wenn sich das zugehörige Zertifikat im TrustedPeople-Speicher befindet. Diese Einstellung ist besser für die Tokenausstellerprüfung geeignet als das standardmäßige "PeerOrChainTrust", da das vertrauenswürdige Zertifikat explizit im Zertifikatsspeicher installiert sein muss. "PeerOrChainTrust" gibt an, dass Signaturen auch autorisiert sind, wenn die Stammzertifizierungsstelle (CA) vertrauenswürdig ist, wozu auf den meisten Rechnern eine beträchtliche Liste an vertrauenswürdigen CAs gehört.

Ich werde kurz einige andere Einstellungen aus Abbildung 5 und Abbildung 6 erläutern. Ein weiterer Punkt zum Thema WIF-Initialisierung ist, dass Sie auch durch Programmierung eine Instanz von "FederatedServiceCredentials" initialisieren und an "ConfigureServiceHost" übergeben können, statt sie über den Abschnitt "microsoft.identityModel" zu initialisieren. Der folgende Beispielcode veranschaulicht dies:

ServiceHost host = new ServiceHost(typeof(TodoList.TodoListService));

ServiceConfiguration fedConfig = new ServiceConfiguration();
fedConfig.IssuerNameRegistry = new TrustedIssuerNameRegistry();
fedConfig.AudienceRestriction.AudienceMode = AudienceUriMode.Always;
fedConfig.AudienceRestriction.AllowedAudienceUris.Add(new 
Uri("http://localhost:8000/TodoListService"));
fedConfig.CertificateValidationMode = 
X509CertificateValidationMode.PeerTrust;
fedConfig.ServiceCertificate = CertificateUtil.GetCertificate(
StoreName.My, StoreLocation.LocalMachine, "CN=RP");

FederatedServiceCredentials fedCreds = 
new FederatedServiceCredentials(fedConfig);

FederatedServiceCredentials.ConfigureServiceHost(host,fedConfig);
host.Open();

Die Initialisierung durch Programmierung ist besonders bei der Initialisierung von "ServiceHost" über die Datenbankeinstellungen, die für eine gesamte Serverfarm gelten, hilfreich.

WIF-Komponentenarchitektur

Wenn Sie WIF-Verhalten auf einen ServiceHost anwenden, werden mehrere WIF-Komponenten initialisiert, um anspruchsbasierte Autorisierung zu ermöglichen. Viele davon sind WCF-Erweiterungen. Dies führt letztendlich dazu, dass "ClaimsPrincipal" an den Anforderungsthread angefügt wird, um anspruchsbasierte Autorisierung zu unterstützen. Abbildung 7 zeigt die Beziehung zwischen den WIF-Kernkomponenten und ServiceHost.


Abbildung 7 Mit WIF installierte Kernkomponenten

Der "FederatedServiceCredentials"-Typ ersetzt das standardmäßige "ServiceCredentials"-Verhalten, und "IdentityModelServiceAuthorizationManager" (wird während der Initialisierung von "FederatedServiceCredentials" installiert) ersetzt das standardmäßige "ServiceAuthorization"-Verhalten. "FederatedServiceCredentials" erstellt außerdem eine "FederatedSecurityTokenManager"-Instanz.  Alle zusammen steuern diese Typen die Authentifizierung und Autorisierung für jede Anfrage, mit der Unterstützung von "ClaimsAuthenticationManager", "ClaimsAuthorizationManager" und "SecurityTokenHandler" für die jeweilige Anfrage.

Abbildung 8 veranschaulicht den Kommunikationsfluss zu diesen Komponenten, der zum Erstellen eines Sicherheitsprinzipals für den Anforderungsthread (in diesem Fall ein "ClaimsPrincipal"-Typ) und zu Möglichkeiten zur Genehmigung des Zugriffs basierend auf diesem Sicherheitsprinzipal führt.


Abbildung 8 Komponenten, die erstellt und anhand von "ClaimsPrincipal" autorisiert werden können

"FederatedSecurityTokenManager" gibt den entsprechenden Tokenhandler für die Anforderung zurück (in diesem Fall "Saml11SecurityTokenHandler") und übergibt zusammen damit einen Verweis auf "ClaimsAuthorizationManager". Der Tokenhandler erstellt eine Anspruchsidentität ("ClaimsIdentity") aus dem eingehenden Token, erstellt den "ClaimsPrincipal" (über eine Wrapperklasse) und übergibt ihn an die "ValidateToken"-Methode für "ClaimsAuthorizationManager". Dies bietet eine Möglichkeit zum Ändern oder Ersetzen des "ClaimsPrincipal", der an den Anforderungsthread angefügt wird. Die Standardimplementierung gibt lediglich den bereitgestellten "ClaimsPrincipal" zurück:

public virtual IClaimsPrincipal Authenticate(string resourceName, IClaimsPrincipal incomingPrincipal)
{
    return incomingPrincipal;
}

Sie können gegebenenfalls einen benutzerdefinierten "ClaimsAuthenticationManager" bereitstellen, um die eingehenden Ansprüche vom Sicherheitstoken so umzuwandeln, dass die RP sie zur Zugriffsautorisierung verwenden kann. In diesem Beispiel überträgt jedoch das SAML-Token die entsprechenden RP-Ansprüche, die vom RP-STS ausgestellt wurden, daher ist der aus diesen Ansprüchen erstellte "ClaimsPrincipal" für die Autorisierung geeignet.

Anschließend ruft der "IdentityModelServiceAuthorizationManager", der auf den "ClaimsAuthorizationManager" verweist, dessen "CheckAccess"-Methode auf, und bietet so eine Möglichkeit, die Zugriffssteuerung anzupassen. Die Standardimplementierung schränkt den Zugriff nicht ein:

public virtual bool CheckAccess(AuthorizationContext context)
{
    return true;
}

Der Parameter "AuthorizationContext" (Autorisierungskontext) gewährleistet den Zugriff auf den "ClaimsPrincipal" und die zugehörigen Ansprüche, eine Sammlung von Aktionen, die für die Anforderung relevant sind (z. B. eine URI, die den aufzurufenden Dienstvorgang angibt) sowie Informationen über die Ressource, die mit der Anforderung verknüpft ist (z. B. die Dienst-URI). Dies ist hilfreich, um Aufrufe für mehrere Dienste zu unterscheiden, die denselben Autorisierungspfad durchlaufen. Zur Implementierung einer zentralen Autorisierung können Sie einen benutzerdefinierten "ClaimsAuthorizationManager" bereitstellen. Bei der Erläuterung der Autorisierungstechniken finden Sie ein Beispiel dazu.

Rollenbasierte Sicherheit im .NET Framework beruht auf der Voraussetzung, dass ein Sicherheitsprinzipal basierend auf IPrincipal an jeden Thread angefügt wird, und dass dieser Sicherheitsprinzipal die Identität des authentifizierten Benutzers in einer IIdentity-Implementierung mit einem Wrapper versieht. Ohne WIF fügt WCF jedem Anforderungsthread basierend auf der "system.serviceModel"-Konfiguration für Authentifizierung und Autorisierung einen Sicherheitsprinzipal hinzu. Basierend auf dem Typ der zur Authentifizierung angebotenen Anmeldeinformationen wird ein IIdentity-Typ erstellt. Beispiel: Windows-Anmeldeinformationen werden anhand einer WindowsIdentity ausgewertet, ein X.509-Zertifikat anhand einer X509Identity und das Token "UserName" anhand von GenericIdentity. "ServiceAuthorizationBehavior" steuert den Typ des IPrincipal-Wrappers für die Identität. Mit einer Windows-Autorisierung wird beispielsweise ein WindowsPrincipal erstellt, mit dem ASP.NET Mitgliedschaftsanbieter ein RoleProviderPrincipal. Alternativ kann eine benutzerdefinierte Autorisierungsrichtlinie zum Erstellen eines IPrincipal-Objekts Ihrer Wahl verwendet werden. Das IPrincipal-Objekt stellt eine "IsInRole"-Methode zur Verfügung, die direkt oder indirekt über Berechtigungsanforderungen aufgerufen werden kann, um den Zugriff auf Merkmale und Funktionen zu steuern.

WIF erweitert dieses Modell durch Bereitstellung von "ClaimsPrincipal"- und "ClaimsIdentity"-Typen (basierend auf "IClaimsPrincipal" und "IClaimsIdentity"), die sich letztendlich von "IPrincipal" und "IIdentity" ableiten. Alle Token werden mit WIF einer Anspruchsidentität ("ClaimsIdentity") zugeordnet. Während jedes eingehende Sicherheitstoken überprüft wird, erstellt der zugehörige "SecurityTokenHandler"-Typ eine "ClaimsIdentity", die die entsprechenden Ansprüche bereitstellt. Diese "ClaimsIdentity" wird in eine "ClaimsIdentityCollection" (Sammlung von Anspruchsidentitäten) eingeschlossen (falls ein Token mehrere "ClaimsIdentity"-Instanzen erzeugt); diese Sammlung wird dann in einen "ClaimsPrincipal" eingeschlossen und an den Anforderungsthread angefügt. Dieser "ClaimsPrincipal" ist das Herzstück der WIF-Autorisierung für Ihre WCF-Dienste.

Anspruchsbasierte Autorisierung

Für WCF-Dienste umfasst Ihre Vorgehensweise bei der Autorisierung wahrscheinlich eine der folgenden Methoden:

  • Verwenden Sie "ClaimsPrincipal" zur Durchführung dynamischer "IsInRole"-Überprüfungen.
  • Verwenden Sie den "PrincipalPermission"-Typ zur Durchführung dynamischer Berechtigungsanforderungen.
  • Verwenden Sie "PrincipalPermissionAttribute" zur Bereitstellung deklarativer Berechtigungsanforderungen bei jedem Vorgang.
  • Stellen Sie einen benutzerdefinierten "ClaimsAuthorizationManager" für die zentrale Zugriffsprüfung in einer einzelnen Komponente bereit.

Die ersten drei dieser Optionen beruhen letztendlich auf der Methode "IsInRole", die vom "ClaimsPrincipal"-Typ zur Verfügung gestellt wird. Das heißt nicht, dass Sie rollenbasierte Sicherheit verwenden. Es heißt lediglich, dass Sie einen Rollenanspruchstyp auswählen, damit die richtigen Ansprüche anhand der angeforderten, an "IsInRole" übergebenen Ansprüche überprüft werden. Der standardmäßige Rollenanspruchstyp für WIF ist "schemas.microsoft.com/ws/2008/06/identity/claims/role". Falls der mit dem Verbundszenario verknüpfte STS diesen Anspruchstyp ausstellt, können Sie optional den Zugriff basierend auf diesem Anspruchstyp steuern. Für das TodoList-Anwendungsszenario habe ich bereits erwähnt, dass ein benutzerdefinierter Berechtigungsanspruchstyp für die Autorisierung verwendet wird, sodass die Identitätsmodellkonfiguration diesen als Rollenanspruchstyp angeben muss, um "IsInRole"-Überprüfungen zu ermöglichen.

Sie übergeben den Rollenanspruchstyp für den erwarteten Tokentyp an den "SecurityTokenHandler", in diesem Fall "Saml11SecurityTokenHandler". Wie in Abbildung 6 dargestellt ist, können Sie die Standardkonfiguration für einen "SecurityTokenHandler" ändern, indem Sie ihn entfernen und dann erneut mit den gewünschten Eigenschaften hinzufügen. SAML-Tokenhandler enthalten einen Abschnitt "samlSecurityTokenRequirement", in dem Sie eine Einstellung für den Namen oder den Rollenanspruchstyp sowie andere Einstellungen bezüglich der Zertifikatsprüfung und Windows-Token angeben können. Für dieses Szenario habe ich einen benutzerdefinierten Rollenanspruchstyp angegeben:

<samlSecurityTokenRequirement >
  <roleClaimType value= "urn:TodoListApp/2009/06/claims/permission"/>
</samlSecurityTokenRequirement>

Das bedeutet, dass bei jedem Aufruf von "IsInRole" für "ClaimsPrincipal" auf einen gültigen Berechtigungsanspruch geprüft wird. Eine Möglichkeit, dies zu erzielen, ist der explizite Aufruf von "IsInRole", bevor ein Codeabschnitt ausgeführt wird, der einen bestimmten Anspruch erfordert. Sie können den aktuellen Prinzipal über die Eigenschaft "Thread.CurrentPrincipal" wie folgt aufrufen:

if (!Thread.CurrentPrincipal.
IsInRole("urn:TodoListApp/2009/06/claims/permission/delete"))
  throw new SecurityException("Access is denied.");

Abgesehen von expliziten "IsInRole"-Überprüfungen zur Laufzeit können Sie auch klassische rollenbasierte Berechtigungsanforderungen mit dem "PrincipalPermission"-Typ schreiben. Sie initialisieren den Typ mit dem erforderlichen Rollenanspruch (der zweite Konstruktorparameter), und sobald "Demand" (Anfordern) aufgerufen wird, wird die "IsInRole"-Methode des aktuellen Prinzipals aufgerufen. Wenn der Anspruch nicht gefunden wird, wird eine Ausnahme ausgelöst:

PrincipalPermission p = new PrincipalPermission("", "urn:TodoListApp/2009/06/claims/permission/delete");
p.Demand();

Sie können auch einen Berechtigungssatz ("PermissionSet") erstellen, um mehrere zu überprüfende Ansprüche zusammenzufassen:

PermissionSet ps = new PermissionSet(PermissionState.Unrestricted);
ps.AddPermission(new PrincipalPermission("", "urn:TodoListApp/2009/06/claims/permission/create"));
ps.AddPermission(new PrincipalPermission("", "urn:TodoListApp/2009/06/claims/permission/read"));
ps.Demand();

Wenn Zugriffsüberprüfungen auf den gesamten Dienstvorgang zutreffen, können Sie stattdessen das "PrincipalPermissionAttribute" anwenden, das eine gute Möglichkeit bietet, erforderliche Ansprüche deklarativ mit dem aufgerufenen Vorgang zu verknüpfen. Diese Attribute können auch gestapelt werden, um mehrere Ansprüche zu überprüfen:

[PrincipalPermission(SecurityAction.Demand, Role = Constants.Permissions.Create)]
[PrincipalPermission(SecurityAction.Demand, Role = Constants.Permissions.Read)]
public string CreateItem(TodoItem item)

In einigen Fällen ist es sinnvoll, die Autorisierung für eine einzelne Komponente zu zentralisieren, was bedeutet, dass Sie einen benutzerdefinierten "ClaimsAuthorizationManager" bereitstellen, um die Zugriffsüberprüfungen durchzuführen. In Abbildung 6 wird die Konfiguration eines benutzerdefinierten "ClaimsAuthorizationManager" veranschaulicht, und die Implementierung für "TodoListService" ist in Abbildung 9 dargestellt (teilweise abgekürzt).

Abbildung 9 Benutzerdefinierte "ClaimsAuthorizationManager"-Implementierung

class CustomClaimsAuthorizationManager : ClaimsAuthorizationManager
{
    public CustomClaimsAuthorizationManager()
    {
    }

    public override bool CheckAccess(AuthorizationContext context)
    {
        
        if (context.Resource.Where(x=> x.ClaimType == 
            System.IdentityModel.Claims.ClaimTypes.Name && x.Value == 
            "http://localhost:8000/TodoListService").Count() > 0)
        {
            if (context.Action.Where(x=> x.ClaimType == 
                System.IdentityModel.Claims.ClaimTypes.Name && x.Value == 
                Constants.Actions.GetItems).Count() > 0)
            {
                return
                    context.Principal.IsInRole(
                       Constants.Permissions.Read);
            }

        // other action checks for TodoListService
        }
        return false;
    }  
}

"ClaimsAuthorizationManager" stellt die Überschreibung von "CheckAccess" (Zugriffsüberprüfung) bereit, der wiederum einen "AuthorizationContext"-Parameter mit Verweis auf die Ressource erhält (in diesem Fall die Dienst-URI); eine Sammlung von Aktionen (in diesem Fall eine einzelne Aktion, die die Dienstvorgangs-URI angibt); und den "ClaimsPrincipal", der noch nicht an den Anforderungsthread angefügt wurde. Sie können die Ressource überprüfen, wenn die Komponente in mehreren Diensten verwendet wird, wie in diesem Beispiel veranschaulicht ist. Hauptsächlich überprüfen Sie die Aktion anhand einer Liste von Dienstvorgangs-URIs und führen "IsInRole"-Überprüfungen entsprechend der Anforderungen des Vorgangs durch.

Normalerweise bin ich nicht dafür, die Autorisierungsüberprüfung von einem geschützten Vorgang oder Codeblock abzukoppeln. Aber es ist viel einfacher, Code zu verwalten, der an einem Ort im Kontext mit der Aktivität deklariert ist.

Fortsetzung folgt

Nun sollten Sie einen guten Überblick darüber haben, wie Sie ein aktives Verbundszenario mit WCF und WIF einrichten, einschließlich Einblicke in die Verbund-Bindungen für WCF und Proxygenerierungs-Semantik; den Ausstellungsprozess für Token; Konfiguration von WIF im Dienst sowie Implementierung verschiedener anspruchsbasierter Autorisierungsmethoden. Im folgenden Artikel fahre ich mit dem passiven Verbund mit ASP.NET und WIF fort.

Michele Leroux Bustamante ist leitende Architektin bei IDesign, Microsoft Regional Director für San Diego und Microsoft-MVP für verbundene Systeme. Ihr aktuelles Buch ist "Learning WCF". Sie können sie unter mlb@idesign.net erreichen, oder besuchen Sie idesign.net.