Benutzernamen- und Kennwort-Validierungssteuerelement
Dieses Beispiel veranschaulicht, wie ein benutzerdefiniertes UserNamePassword-Validierungssteuerelement implementiert wird. Dies ist nützlich, wenn keines der integrierten UserNamePassword-Validierungsmodi den Anforderungen der Anwendung entspricht (z. B. wenn Benutzername/Kennwort-Paare in externen Speichern wie einer Datenbank gespeichert werden). In diesem Beispiel wird ein Dienst gezeigt, der ein benutzerdefiniertes Validierungssteuerelement enthält, das auf zwei bestimmte Benutzername/Kennwort-Paare überprüft. Der Client verwendet solch ein Benutzername/Kennwort-Paar, um sich beim Dienst zu authentifizieren.
Tipp
Da jeder eine Benutzername-Anmeldeinformation mit den Benutzername/Kennwort-Paaren erstellen kann, die das benutzerdefinierte Steuerelement akzeptiert, ist der Dienst weniger sicher als das Standardverhalten des normalen UserNamePassword-Validierungssteuerelements. Das normale UserNamePassword-Validierungssteuerelement versucht, das angegebene Benutzername/Kennwort-Paar einem Windows-Konto zuzuordnen. Schlägt diese Zuordnung fehl, wird die Authentifizierung mit einem Fehler abgebrochen. Das benutzerdefinierte UserNamePassword-Validierungssteuerelement aus diesem Beispiel DARF NICHT in Produktionscode verwendet werden, es dient nur zur Veranschaulichung.
Insgesamt zeigt dieses Beispiel Folgendes:
- Der Client kann mit einem Benutzernamentoken authentifiziert werden.
- Der Server überprüft die Clientanmeldeinformationen anhand eines benutzerdefinierten UserNamePasswordValidator und wie benutzerdefinierte Fehler aus der Logik zur Überprüfung von Benutzername und Kennwort an den Client weitergegeben werden.
- Der Server wird mit dem X.509-Zertifikat des Servers authentifiziert.
Der Dienst macht einen einzelnen Endpunkt zur Kommunikation mit dem Dienst verfügbar, der mit der Konfigurationsdatei "App.conf" definiert wird. Der Endpunkt besteht aus einer Adresse, einer Bindung und einem Vertrag. Die Bindung wird mit einer normalen wsHttpBinding konfiguriert, die standardmäßig WS-Security und Benutzernamenauthentifizierung verwendet. Das Dienstverhalten gibt den Custom-Modus zum Überprüfen von Benutzername/Kennwort-Paaren zusammen mit dem Typ der Validierungssteuerelementklasse an. Das Verhalten gibt auch das Serverzertifikat mit dem serviceCertificate-Element an. Das Serverzertifikat muss für den SubjectName denselben Wert wie das findValue in dem serviceCertificate element of serviceCredentials enthalten.
<system.serviceModel>
<services>
<service name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<!-- use host/baseAddresses to configure base address provided by host -->
<host>
<baseAddresses>
<add baseAddress ="https://localhost:8001/servicemodelsamples/service" />
</baseAddresses>
</host>
<!-- use base address specified above, provide one endpoint -->
<endpoint address="username"
binding="wsHttpBinding"
bindingConfiguration="Binding"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<!-- username binding -->
<binding name="Binding">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults ="true"/>
<serviceCredentials>
<!--
The serviceCredentials behavior allows one to
specify a custom validator for username/password
combinations.
-->
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.CalculatorService+MyCustomUserNameValidator, service" />
<!--
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.
-->
<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 Modus und der clientCredentialType-Nachricht konfiguriert.
<system.serviceModel>
<client>
<!-- Username based endpoint -->
<endpoint name="Username"
address="https://localhost:8001/servicemodelsamples/service/username"
binding="wsHttpBinding"
bindingConfiguration="Binding"
behaviorConfiguration="ClientCertificateBehavior"
contract="Microsoft.ServiceModel.Samples.ICalculator">
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<!-- Username binding -->
<binding name="Binding">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<serviceCertificate>
<!--
Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate
is in the user's Trusted People store, then it will be trusted without performing a
validation of the certificate's issuer chain. This setting is used here for convenience so that the
sample can be run without having to have certificates issued by a certification authority (CA).
This setting is less secure than the default, ChainTrust. The security implications of this
setting should be carefully considered before using PeerOrChainTrust in production code.
-->
<authentication certificateValidationMode="PeerOrChainTrust" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Die Clientimplementierung fordert den Benutzer auf, einen Benutzernamen und ein Kennwort einzugeben.
// Get the username and password
Console.WriteLine("Username authentication required.");
Console.WriteLine("Provide a username.");
Console.WriteLine(" Enter username: (test1)");
string username = Console.ReadLine();
Console.WriteLine(" Enter password:");
string password = "";
ConsoleKeyInfo info = Console.ReadKey(true);
while (info.Key != ConsoleKey.Enter)
{
if (info.Key != ConsoleKey.Backspace)
{
if (info.KeyChar != '\0')
{
password += info.KeyChar;
}
info = Console.ReadKey(true);
}
else if (info.Key == ConsoleKey.Backspace)
{
if (password != "")
{
password = password.Substring(0, password.Length - 1);
}
info = Console.ReadKey(true);
}
}
for (int i = 0; i < password.Length; i++)
{
Console.Write("*");
}
Console.WriteLine();
// Create a proxy with Certificate endpoint configuration
CalculatorProxy proxy = new CalculatorProxy("Username")
try
{
proxy.ClientCredentials.Username.Username = username;
proxy.ClientCredentials.Username.Password = password;
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = proxy.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
}
catch (Exception e)
{
Console.WriteLine("Call failed:");
while (e != null)
{
Console.WriteLine("\t{0}", e.Message);
e = e.InnerException;
}
proxy.Abort();
}
}
In diesem Beispiel wird ein benutzerdefinierter UserNamePasswordValidator verwendet, um Benutzername/Kennwort-Paare zu überprüfen. Das Beispiel implementiert CustomUserNamePasswordValidator
, das von UserNamePasswordValidator abgeleitet ist. Weitere Informationen finden Sie in der Dokumentation zu UserNamePasswordValidator. Dieses Beispiel zu einem benutzerdefinierten Validierungssteuerelement implementiert die Validate
-Methode zum Akzeptieren zweier bestimmter Benutzername/Kennwort-Paare, wie im folgenden Code gezeigt.
public class CustomUserNameValidator : UserNamePasswordValidator
{
// This method validates users. It allows in two users,
// test1 and test2 with passwords 1tset and 2tset respectively.
// This code is for illustration purposes only and
// MUST NOT be used in a production environment because it
// is NOT secure.
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (!(userName == "test1" && password == "1tset") && !(userName == "test2" && password == "2tset"))
{
throw new FaultException("Unknown Username or Incorrect Password");
}
}
}
Wenn das Validierungssteuerelement im Dienstcode implementiert ist, muss der Diensthost über die zu verwendende Validierungssteuerelementinstanz informiert werden. Dies wird mit dem folgenden Code durchgeführt.
serviceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
serviceHost.Credentials. UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNamePasswordValidator();
Sie können dasselbe aber auch wie folgt in der Konfiguration vornehmen.
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
...
<serviceCredentials>
<!--
The serviceCredentials behavior allows one to specify authentication constraints on username / password combinations.
-->
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.CalculatorService+CustomUserNameValidator, service" />
...
</behavior>
</serviceBehaviors>
</behaviors>
Wenn Sie das Beispiel ausführen, werden die Anforderungen und Antworten für den Vorgang im Clientkonsolenfenster angezeigt. Der Client sollte alle Methoden erfolgreich aufrufen. 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 selbst gehosteten Fall funktioniert.
Nachfolgend erhalten Sie einen kurzen Überblick über die verschiedenen Abschnitte der Batchdateien, damit Sie sie so ändern 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, um einen eigenen Servernamen anzugeben. Der Standardwert ist "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 -pe
Installieren des Serverzertifikats in den Clientspeicher für vertrauenswürdige Zertifikate:
Mit den folgenden Zeilen in der Batchdatei "Setup.bat" 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, das 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 TrustedPeople
So richten Sie das Beispiel ein und erstellen es
Folgen Sie zum Erstellen der Lösung den unter Erstellen der Windows Communication Foundation-Beispiele aufgeführten Anweisungen.
Wenn Sie das Beispiel in einer Konfiguration mit einem einzigen Computer oder computerübergreifend ausführen möchten, folgen Sie den folgenden Anweisungen.
So führen Sie das Beispiel auf demselben Computer aus
Stellen Sie sicher, dass der Pfad den Ordner enthält, in dem sich Makecert.exe befindet.
Führen Sie Setup.bat aus dem Beispielinstallationsordner aus. Dadurch werden alle Zertifikate, die zum Ausführen des Beispiels erforderlich sind, installiert.
Starten Sie "Service.exe" aus dem Ordner "service\bin".
Starten Sie "Client.exe" aus dem Ordner "\client\bin". In der Clientkonsolenanwendung wird Clientaktivität angezeigt.
Wenn 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 Konfigurationsdatei für den Server muss entsprechend aktualisiert werden, dass sie diesen neuen Zertifikatsnamen wiedergibt.
Kopieren Sie das Serverzertifikat in den CurrentUser-TrustedPeople-Speicher des Clients. Dies ist nur dann erforderlich, wenn das Serverzertifikat nicht von einem vertrauenswürdigen Aussteller ausgegeben wurde.
Ändern Sie in der Datei "App.config" auf dem Dienstcomputer den Wert der Basisadresse, um anstelle von "localhost" einen vollqualifizierten Computernamen anzugeben.
Starten Sie auf dem Dienstcomputer Service.exe in einem Eingabeaufforderungsfenster.
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 "Client.exe" in einem Eingabeaufforderungsfenster.
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. Dadurch wird das Serverzertifikat aus dem Zertifikatspeicher entfernt.
Send comments about this topic to Microsoft.
© 2007 Microsoft Corporation. All rights reserved.