Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dieses Beispiel veranschaulicht das Implementieren eines benutzerdefinierten Tokenauthentifizierers. Mithilfe eines Tokenauthentifizierers in Windows Communication Foundation (WCF) wird das mit der Nachricht verwendete Token überprüft. Außerdem wird überprüft, ob es in sich selbst konsistent ist, und die Identität des Tokens wird authentifiziert.
Benutzerdefinierte Tokenauthentifizierer sind in einer Vielzahl von Fällen nützlich, z. B.:
- Wenn Sie den einem Token zugeordneten Standardauthentifizierungsmechanismus überschreiben möchten.
- Wenn Sie ein benutzerdefiniertes Token erstellen.
Dieses Beispiel zeigt Folgendes:
- Wie sich ein Client mithilfe eines Benutzername/Kennwort-Paars authentifizieren kann.
- Wie der Server die Clientanmeldeinformationen mit einem benutzerdefinierten Tokenauthentifizierer überprüfen kann.
- Wie der WCF-Dienstcode mit dem benutzerdefinierten Tokenauthentifizierer übereinstimmt.
- Wie der Server mit dem X.509-Zertifikat des Servers authentifiziert werden kann.
In diesem Beispiel wird auch gezeigt, wie in WCF auf die Identität des Aufrufers nach dem benutzerdefinierten Tokenauthentifizierungsprozess zugegriffen werden kann.
Der Dienst macht einen einzelnen Endpunkt zur Kommunikation mit dem Dienst verfügbar, der mit der App.conf-Konfigurationsdatei definiert wird. Der Endpunkt besteht aus einer Adresse, einer Bindung und einem Vertrag. Die Bindung wird mit einem Standard-wsHttpBinding konfiguriert, wobei der Sicherheitsmodus auf "Nachricht" festgelegt ist. Dies ist der Standardmodus von wsHttpBinding. In diesem Beispiel wird die Standard-wsHttpBinding auf die Verwendung der Clientbenutzernamenauthentifizierung festgelegt. Außerdem konfiguriert der Dienst das Dienstzertifikat mit serviceCredentials-Verhalten. Mit dem securityCredentials-Verhalten können Sie ein Dienstzertifikat angeben. Ein Dienstzertifikat wird von einem Client verwendet, um den Dienst zu authentifizieren und Nachrichtenschutz bereitzustellen. Die folgende Konfiguration verweist auf das Zertifikat "localhost", das während des Beispielsetups installiert wird, wie im folgenden Setup beschrieben.
<system.serviceModel>
<services>
<service
name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<host>
<baseAddresses>
<!-- configure base address provided by host -->
<add baseAddress ="https://localhost:8000/servicemodelsamples/service" />
</baseAddresses>
</host>
<!-- use base address provided by host -->
<endpoint address=""
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults="False" />
<!--
The serviceCredentials behavior allows one to define a service certificate.
A service certificate is used by a client to authenticate the service and provide message protection.
This configuration references the "localhost" certificate installed during the setup instructions.
.... -->
<serviceCredentials>
<serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Die Clientendpunktkonfiguration besteht aus einem Konfigurationsnamen, einer absoluten Adresse für den Dienstendpunkt, der Bindung und dem Vertrag. Die Clientbindung wird mit dem entsprechenden Mode und clientCredentialType konfiguriert.
<system.serviceModel>
<client>
<endpoint name=""
address="https://localhost:8000/servicemodelsamples/service"
binding="wsHttpBinding"
bindingConfiguration="Binding1"
contract="Microsoft.ServiceModel.Samples.ICalculator">
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
Die Clientimplementierung legt den zu verwendenden Benutzernamen und das Kennwort fest.
static void Main()
{
...
client.ClientCredentials.UserNamePassword.UserName = username;
client.ClientCredentials.UserNamePassword.Password = password;
...
}
Benutzerdefinierter Tokenauthentifizierer
Führen Sie die folgenden Schritte aus, um einen benutzerdefinierten Tokenauthentifizierer zu erstellen:
Erstellen Sie einen benutzerdefinierten Tokenauthentifizierer.
Im Beispiel wird ein benutzerdefinierter Tokenauthentifizierer implementiert, der überprüft, ob der Benutzername ein gültiges E-Mail-Format hat. Er ermittelt den UserNameSecurityTokenAuthenticator. Die wichtigste Methode in dieser Klasse ist ValidateUserNamePasswordCore. In dieser Methode überprüft der Authentifizierer das Format des Benutzernamens und kontrolliert, ob der Hostname von einer nicht autorisierten Domäne stammt. Wenn beide Bedingungen erfüllt sind, gibt er eine schreibgeschützte Auflistung von IAuthorizationPolicy-Instanzen zurück, mit der Ansprüche bereitgestellt werden, die die Informationen im Benutzernamentoken darstellen.protected override ReadOnlyCollection<IAuthorizationPolicy> ValidateUserNamePasswordCore(string userName, string password) { if (!ValidateUserNameFormat(userName)) throw new SecurityTokenValidationException("Incorrect UserName format"); ClaimSet claimSet = new DefaultClaimSet(ClaimSet.System, new Claim(ClaimTypes.Name, userName, Rights.PossessProperty)); List<IIdentity> identities = new List<IIdentity>(1); identities.Add(new GenericIdentity(userName)); List<IAuthorizationPolicy> policies = new List<IAuthorizationPolicy>(1); policies.Add(new UnconditionalPolicy(ClaimSet.System, claimSet, DateTime.MaxValue.ToUniversalTime(), identities)); return policies.AsReadOnly(); }Geben Sie eine Autorisierungsrichtlinie an, die vom benutzerdefinierten Tokenauthentifizierer zurückgegeben wird.
Dieses Beispiel enthält seine eigene Implementierung von IAuthorizationPolicy, die alsUnconditionalPolicybezeichnet wird und Sätze von Ansprüchen und Identitäten zurückgibt, die in ihrem Konstruktor an sie übergeben wurden.class UnconditionalPolicy : IAuthorizationPolicy { String id = Guid.NewGuid().ToString(); ClaimSet issuer; ClaimSet issuance; DateTime expirationTime; IList<IIdentity> identities; public UnconditionalPolicy(ClaimSet issuer, ClaimSet issuance, DateTime expirationTime, IList<IIdentity> identities) { if (issuer == null) throw new ArgumentNullException("issuer"); if (issuance == null) throw new ArgumentNullException("issuance"); this.issuer = issuer; this.issuance = issuance; this.identities = identities; this.expirationTime = expirationTime; } public string Id { get { return this.id; } } public ClaimSet Issuer { get { return this.issuer; } } public DateTime ExpirationTime { get { return this.expirationTime; } } public bool Evaluate(EvaluationContext evaluationContext, ref object state) { evaluationContext.AddToTarget(this, this.issuance); if (this.identities != null) { object value; IList<IIdentity> contextIdentities; if (!evaluationContext.Properties.TryGetValue("Identities", out value)) { contextIdentities = new List<IIdentity>(this.identities.Count); evaluationContext.Properties.Add("Identities", contextIdentities); } else { contextIdentities = value as IList<IIdentity>; } foreach (IIdentity identity in this.identities) { contextIdentities.Add(identity); } } evaluationContext.RecordExpirationTime(this.expirationTime); return true; } }Schreiben Sie den benutzerdefinierten Sicherheitstoken-Manager.
Mit dem SecurityTokenManager wird ein SecurityTokenAuthenticator für bestimmte SecurityTokenRequirement-Objekte erstellt, die in derCreateSecurityTokenAuthenticator-Methode an ihn übergeben werden. Der Sicherheitstoken-Manager dient außerdem zum Erstellen von Tokenanbietern und Token-Serialisierungsprogrammen. Diese Vorgänge werden in diesem Beispiel jedoch nicht behandelt. In diesem Beispiel erbt der benutzerdefinierte Sicherheitstoken-Manager aus der Klasse ServiceCredentialsSecurityTokenManager und überschreibt die MethodeCreateSecurityTokenAuthenticator, um benutzerdefinierte Benutzernamen-Tokenauthentifizierer zurückzugeben, wenn die übergebenen Tokenanforderungen angeben, dass der Benutzernamenauthentifizierer angefordert wird.public class MySecurityTokenManager : ServiceCredentialsSecurityTokenManager { MyUserNameCredential myUserNameCredential; public MySecurityTokenManager(MyUserNameCredential myUserNameCredential) : base(myUserNameCredential) { this.myUserNameCredential = myUserNameCredential; } public override SecurityTokenAuthenticator CreateSecurityTokenAuthenticator(SecurityTokenRequirement tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver) { if (tokenRequirement.TokenType == SecurityTokenTypes.UserName) { outOfBandTokenResolver = null; return new MyTokenAuthenticator(); } else { return base.CreateSecurityTokenAuthenticator(tokenRequirement, out outOfBandTokenResolver); } } }Erstellen Sie benutzerdefinierte Dienstanmeldeinformationen.
Die Klasse der Dienstanmeldeinformationen stellt die Anmeldeinformationen dar, die für den Dienst konfiguriert werden, und erstellt einen Sicherheitstoken-Manager, mit dem Tokenauthentifizierer, Tokenanbieter und Token-Serialisierungsprogramme abgerufen werden können.public class MyUserNameCredential : ServiceCredentials { public MyUserNameCredential() : base() { } protected override ServiceCredentials CloneCore() { return new MyUserNameCredential(); } public override SecurityTokenManager CreateSecurityTokenManager() { return new MySecurityTokenManager(this); } }Konfigurieren Sie den Dienst für die Verwendung der benutzerdefinierten Dienstanmeldeinformationen.
Damit der Dienst die benutzerdefinierten Dienstanmeldeinformationen verwenden kann, wird die standardmäßige Dienstanmeldeinformationen-Klasse nach dem Abrufen des in den standardmäßigen Dienstanmeldeinformationen vorkonfigurierten Dienstzertifikats gelöscht. Anschließend wird die neue Dienstanmeldeinformationen-Instanz zum Verwenden der vorkonfigurierten Dienstzertifikate konfiguriert und zum Dienstverhalten hinzugefügt.ServiceCredentials sc = serviceHost.Credentials; X509Certificate2 cert = sc.ServiceCertificate.Certificate; MyUserNameCredential serviceCredential = new MyUserNameCredential(); serviceCredential.ServiceCertificate.Certificate = cert; serviceHost.Description.Behaviors.Remove((typeof(ServiceCredentials))); serviceHost.Description.Behaviors.Add(serviceCredential);
Um die Informationen zu den Aufrufern anzuzeigen, können Sie PrimaryIdentity verwenden, wie im folgenden Code gezeigt. Current enthält Informationen zu den Ansprüchen des aktuellen Aufrufers.
static void DisplayIdentityInformation()
{
Console.WriteLine("\t\tSecurity context identity : {0}",
ServiceSecurityContext.Current.PrimaryIdentity.Name);
return;
}
Wenn Sie das Beispiel ausführen, werden die Anforderungen und Antworten für den Vorgang im Clientkonsolenfenster angezeigt. Drücken Sie im Clientfenster die EINGABETASTE, um den Client zu schließen.
Setupbatchdatei
Mit der in diesem Beispiel enthaltenen Setup.bat-Batchdatei können Sie den Server mit relevanten Zertifikaten zum Ausführen einer selbst gehosteten Anwendung konfigurieren, die serverzertifikatbasierte Sicherheit erfordert. Diese Batchdatei muss so geändert werden, dass sie computerübergreifend oder in einem nicht gehosteten Fall funktioniert.
Nachfolgend erhalten Sie einen kurzen Überblick über die verschiedenen Abschnitte der Batchdateien, damit Sie sie so bearbeiten können, dass sie in der entsprechenden Konfiguration ausgeführt werden.
Erstellen des Serverzertifikats.
Mit den folgenden Zeilen aus der Batchdatei "Setup.bat" wird das zu verwendende Serverzertifikat erstellt. Die Variable%SERVER_NAME%gibt den Servernamen an. Ändern Sie diese Variable, und geben Sie Ihren eigenen Servernamen an. Standardmäßig lautet die Variable in dieser Batchdatei "localhost".echo ************ echo Server cert setup starting echo %SERVER_NAME% echo ************ echo making server cert echo ************ makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -peInstallieren des Serverzertifikats in den Clientspeicher für vertrauenswürdige Zertifikate.
Mit den folgenden Zeilen in der Setup.bat-Batchdatei wird das Serverzertifikat in den Clientspeicher für vertrauenswürdige Personen kopiert. Dieser Schritt ist erforderlich, da von "Makecert.exe" generierten Zertifikaten nicht implizit vom Clientsystem vertraut wird. Wenn Sie bereits über ein Zertifikat verfügen, dass von einem vertrauenswürdigen Clientstammzertifikat stammt (z. B. ein von Microsoft ausgegebenes Zertifikat), ist dieser Schritt zum Füllen des Clientzertifikatspeichers mit dem Serverzertifikat nicht erforderlich.certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeopleTipp
Die Setupbatchdatei ist darauf ausgelegt, von einer Windows SDK-Eingabeaufforderung ausgeführt zu werden. Die MSSDK-Umgebungsvariable muss auf das Verzeichnis zeigen, in dem das SDK installiert ist. Diese Umgebungsvariable wird automatisch innerhalb einer Windows SDK-Eingabeaufforderung festgelegt.
So richten Sie das Beispiel ein und erstellen es
Stellen Sie sicher, dass Sie Beispiele zum einmaligen Setupverfahren für Windows Communication Foundation ausgeführt haben.
Befolgen Sie zum Erstellen der Lösung die Anweisungen unter Erstellen der Windows Communication Foundation-Beispiele.
So führen Sie das Beispiel auf demselben Computer aus
Stellen Sie sicher, dass der Pfad den Ordner enthält, indem sich "Makecert.exe" befindet.
Führen Sie "Setup.bat" im Beispielinstallationsordner aus. Dadurch werden alle Zertifikate, die zum Ausführen des Beispiels erforderlich sind, installiert.
Starten Sie "service.exe" in "\service\bin".
Starten Sie "Client.exe" aus "\client\bin". In der Clientkonsolenanwendung wird Clientaktivität angezeigt.
Falls der Client und der Dienst nicht miteinander kommunizieren können, finden Sie weitere Informationen unter Hinweise zur Fehlerbehebung.
So führen Sie das Beispiel computerübergreifend aus
Erstellen Sie auf dem Dienstcomputer ein Verzeichnis für die Dienstbinärdateien.
Kopieren Sie die Dienstprogrammdateien in das Dienstverzeichnis auf dem Dienstcomputer. Kopieren Sie außerdem die Dateien "Setup.bat" und "Cleanup.bat" auf den Dienstcomputer.
Sie benötigen ein Serverzertifikat mit dem Antragstellernamen, das den vollqualifizierten Domänennamen des Computers enthält. Die Datei "App.config" des Diensts muss so aktualisiert werden, dass sie diesem neuen Zertifikatnamen entspricht. Mithilfe von "Setup.bat" können Sie einen solchen erstellen, wenn Sie die Variable
%SERVER_NAME%als vollqualifizierten Hostnamen des Computers festlegen, auf dem der Dienst ausgeführt wird.Kopieren Sie das Serverzertifikat in den CurrentUser-TrustedPeople-Speicher des Clients. Sie müssen diesen Schritt nur dann ausführen, wenn das Serverzertifikat von einem Aussteller stammt, der vom Client als vertrauenswürdig eingestuft wurde.
Ändern Sie in der Datei "App.config" auf dem Dienstcomputer den Wert der Basisadresse, um anstelle von "localhost" einen vollqualifizierten Computernamen anzugeben.
Führen Sie auf dem Dienstcomputer die Datei "service.exe" über eine Eingabeaufforderung aus.
Kopieren Sie die Clientprogrammdateien aus dem Ordner "\client\bin\" (unterhalb des sprachspezifischen Ordners) auf den Clientcomputer.
Ändern Sie in der Datei "Client.exe.config" auf dem Clientcomputer den Wert für die Adresse des Endpunkts so, dass er mit der neuen Adresse Ihres Diensts übereinstimmt.
Starten Sie auf dem Clientcomputer in einer Eingabeaufforderung die Datei "Client.exe".
Wenn der Client und der Dienst nicht miteinander kommunizieren können, finden Sie weitere Informationen unter Hinweise zur Fehlerbehebung.
So bereinigen Sie nach dem Beispiel
- Führen Sie "Cleanup.bat" im Beispielordner aus, nachdem Sie das Beispiel fertig ausgeführt haben.
Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.