Authentifizierung in Web Services - WS-Security, Benutzername / Passwort
Geschrieben von: Christoph Wille Der WS-Security Standard umfasst das Signieren von SOAP Nachrichten, das Verschlüsseln von SOAP Nachrichten, sowie das Anhängen von Security Credentials an SOAP Nachrichten. Diese Security Credentials werden für die Authentifizierung verwendet, und können Benutzername / Passwort, ein X.509 Zertifikat oder Binärtoken sein. Wir beschäftigen uns heute mit ersterem, und werden dies mit Hilfe der Web Services Enhancements (WSE) 1.0 unter .NET implementieren. Die XML Web Services Downloads Seite enthält die aktuellsten Links zu den Web Service Enhancements. Für diesen Artikel wurden Server und Client-seitig das Web Services Enhancements 1.0 SP1 for Microsoft .NET, und auf der Entwicklermaschine (VS.NET 2002 oder 2003 vorausgesetzt) zusätzlich das Web Services Enhancements Settings Tool for Visual Studio .NET eingesetzt. Bitte installieren Sie diese Tools entsprechend. Die Benutzername / Passwort Authentifizierung des WS-Security Standards ist im Web Services Enhancements (WSE) über die UsernameToken Klasse implementiert. Der Client generiert diesen Token, schickt ihn im Request an den Server, der Server liest ihn aus dem Request aus - und überprüft, ob der User authentifiziert werden kann. Die Überprüfung des UsernameToken passiert in einem vom Entwickler separat zu erstellenden Password Provider, wo man die Authentifizierung gegen beliebige Datenquellen vornehmen kann. Der Password Provider für den Web ServiceUnser erster Schritt ist also, einen Password Provider (im Download als SamplePasswordProvider enthalten) zu implementieren. Dieser ist eine DLL Assembly, und enthält folgenden Code (SimpleProvider.cs): using System; using Microsoft.Web.Services.Security; namespace SamplePasswordProvider { public class Simple : IPasswordProvider { public string GetPassword(UsernameToken token) { // Absicherung, damit wir auf alle Fälle einen Token in der Hand haben if (null == token) throw new ArgumentNullException(); string strUsername = token.Username; return strUsername; } } } Die Funktionalität für WS-Security in den Web Services Enhancements befindet sich im Namespace Microsoft.Web.Services.Security, der über die Assembly Microsoft.Web.Services.dll referenziert wird. Die Password Provider Klasse selbst implementiert das Interface IPasswordProvider, das nur eine einzige Methode hat: GetPassword. Damit wird für einen Benutzernamen das Passwort geliefert - den Vergleich des Passwortes nimmt die WSE Infrastruktur selbst vor, da Passwörter ja gehasht übertragen werden können (oder mittels Decryption Key Provider beliebig verschlüsselt). Kompilieren Sie die Assembly, und merken Sie vor, daß Sie die Assembly in das bin Verzeichnis der Web Service Applikation kopieren müssen! Der Web ServiceErzeugen Sie einen Web Service in Visual Studio .NET, und wie im Assemblyprojekt zuvor, fügen Sie eine Referenz auf die WSE Assembly ein. Nach diesen Vorarbeiten müssen wir die WSE Infrastruktur über die web.config einbinden. Hier kommt das Web Services Enhancements Settings Tool for Visual Studio .NET ins Spiel - dieses kann über das Kontextmenü des Projekts aufgerufen werden ("WSE Settings"): Die erste Tabseite legt fest, ob und welche Features von WSE wir verwenden wollen. Diese Einstellungen passen uns gut, und wir gehen zum Security Tab: Dort geben wir die Assembly sowie den vollen Klassennamen unseres Password Providers an (den Sie in das bin Verzeichnis kopieren). Nach diesem Point-and-Click "Abenteuer" modifiziert uns das Tool automatisch die web.config (Achtung: die Strings type sind nur der Leserlichkeit wegen auf mehrere Zeilen aufgeteilt, in einer lauffähigen web.config müssen diese in einer einzigen Zeile stehen!): <configuration> <configSections> <section name="microsoft.web.services" type="Microsoft.Web.Services.Configuration.WebServicesConfiguration, Microsoft.Web.Services, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </configSections> <microsoft.web.services> <security> <!--namespace.classname, assembly name --> <passwordProvider type="SamplePasswordProvider.Simple, SamplePasswordProvider" /> </security> </microsoft.web.services> <system.web> <webServices> <soapExtensionTypes> <add type="Microsoft.Web.Services.WebServicesExtension,Microsoft.Web.Services, Version=1.0.0.0,Culture=neutral,PublicKeyToken=31bf3856ad364e35" priority="1" group="0" /> </soapExtensionTypes> </webServices> Nach dieser Vorarbeit kommen wir endlich zum Code des Web Services (Projekt UsernameTokenAuth), beginnen wir mit den zusätzlichen Namespace Imports: using Microsoft.Web.Services; using Microsoft.Web.Services.Security; using System.Web.Services.Protocols; Die ersten beiden sind für das WSE, der dritte für die SoapException Klasse, mit der wir Fehler an den Client zurückmelden. Sehen wir uns nun unsere Web Service Methode an: [WebMethod] public string UsernameTokenAuthSampleMethod() { UsernameToken utCurrent = Authenticate(); return "Hello World, " + utCurrent.Username; } Die ganze Arbeit ist wieder in eine Methode namens Authenticate ausgelagert. Im Vergleich zu früheren Beispielen macht sie aber nur Hilfsarbeiten, da die eigentliche Authentifizierung durch WSE und unseren Password Provider erledigt wird. Trotzdem ist der Sourcecode interessant und vor allem auch notwendig: private UsernameToken Authenticate() { // Wir müssen 3 Checks durchführen // * SoapContext muß existieren (SOAP Request & WSE installiert) // * Nur ein UsernameToken darf übergeben worden sein // * Ein Passwort muß übergeben worden sein (Kontrolle auf SendHashed) SoapContext sc = HttpSoapContext.RequestContext; // CHECK 1 if (null == sc) { throw new ApplicationException("Nur SOAP Requests erlaubt"); } // CHECK 2 UsernameToken utCurrent = null; foreach (SecurityToken st in sc.Security.Tokens) { if (st is UsernameToken) { if (null != utCurrent) { // ein zweiter Token wurde übergeben - Abbruch throw new SoapException("Nur ein UsernameToken pro Request erlaubt!", SoapException.ClientFaultCode); } else utCurrent = (UsernameToken)st; } } if (null == utCurrent) throw new SoapException("Kein UsernameToken übergeben", SoapException.ClientFaultCode); // CHECK 3 if (utCurrent.PasswordOption != PasswordOption.SendHashed) throw new SoapException("Falsche Übergabeart für Passwort", SoapException.ClientFaultCode); // alles ok ab hier return utCurrent; } Die drei Fehlerfälle sind leicht erklärt: der erste ist, daß am Client der Webservice ohne WSE aufgerufen wurde, also ein normaler unauthentifizierter Request gestartet wurde. Der zweite Fall ist, daß mehr als ein UsernameToken übergeben wurde - gegen welchen soll authentifiziert werden? Da wir das nicht wissen, brechen wir sicherheitshalber ab. Der dritte Fall ist, daß auf der Clientseite das Passwort nicht gehashed verschickt wurde, also ein leeres Passwort theoretisch möglich wäre - dies ist aus Sicherheitsgründen auch zu unterbinden. Nach all diesen zusätzlichen Checks kann man sicher sein, daß sicherheitstechnisch alles wasserdicht ist. Damit haben wir einen abgesicherten Service, und können uns dem Client zuwenden. Der ClientDas Erstellen der Web Referenz funktioniert automatisch, wenn man das Web Services Enhancements Settings Tool for Visual Studio .NET installiert hat. Wenn nicht, muß man sicherstellen, daß im Web Service Proxy die Klasse so definiert ist: public class Service1 : Microsoft.Web.Services.WebServicesClientProtocol { Die Basisklasse ist geändert - das Tool erledigt das selbständig, ohne Tool muß man diese Änderung per Hand machen. Noch das WSE als Referenz eingebunden, und schon kann man den Client coden (Projekt UsernameTokenAuthClient): using System; // Notwendig für WSE using Microsoft.Web.Services.Security; namespace UsernameTokenAuthClient { class ConsoleAppWsClient { [STAThread] static void Main(string[] args) { localhost.Service1 svc = new localhost.Service1(); // Neuen UsernameToken anlegen, und der Tokens Collection des Request Contexts anhängen UsernameToken ut = new UsernameToken("test", "test", PasswordOption.SendHashed); svc.RequestSoapContext.Security.Tokens.Add(ut); // Und jetzt den Web Service aufrufen string strRetVal = svc.UsernameTokenAuthSampleMethod(); Console.WriteLine(strRetVal); } } } Hierbei ist wichtig darauf zu achten, den RequestSoapContext zu verwenden, weil es gibt auch den ResponseSoapContext - wenn man bei IntelliSense nicht genau schaut, kann das zu einer langwierigen Fehlersuche führen! Ansonsten ist der Code sehr ähnlich zu dem, den wir für Custom SOAP Headers verwendet haben. Dank WSE ist die Implementierung einer Benutzername / Passwort Authentifizierung nach dem WS-Security Standard keine große Affäre - im Prinzip ist es ein Kochrezept, das immer angewendet wird. Die aktuellen SOAP Toolkits unterstützen diesen Standard bereits - auf verschiedensten Plattformen und für verschiedenste Programmiersprachen. SchlußbemerkungDie Benutzername / Passwort Authentifizierung ist eine gute - vor allem standardisierte - Möglichkeit, Authentifizierung bei Web Services zu implementieren. Doch WS-Security bietet noch mehr Authentifizierungsmethoden, und eine davon werden wir im nächsten Artikel beleuchten: X.509 Zertifikate für die Authentifizierung. Download des CodesKlicken Sie hier, um den Download zu starten. Verwandte Artikel
Authentifizierung in Web Services - SOAP Header Links zu anderen Sites
Web Services Enhancements 1.0 SP1 for Microsoft .NET Wenn Sie jetzt Fragen haben...Wenn Sie Fragen rund um die in diesem Artikel vorgestellte Technologie haben, dann schauen Sie einfach bei uns in den Community Foren der deutschen .NET Community vorbei. Die Teilnehmer helfen Ihnen gerne, wenn Sie sich zur im Artikel vorgestellten Technologie weiterbilden möchten. Eine weitere sehr hilfreiche Resource ist das deutsche ASP.NET Wiki, das als zentrale Anlaufstelle für Tips, Tricks, Know How und alles Nützliche was man in seinem Alltag als (ASP).NET-Entwickler so braucht und entdeckt gedacht ist. Haben Sie Fragen die sich direkt auf den Inhalt des Artikels beziehen, dann schreiben Sie dem Autor! Unsere Autoren freuen sich über Feedback zu ihren Artikeln. Ein einfacher Klick auf die Autor kontaktieren Schaltfläche (weiter unten) und schon haben Sie ein für diesen Artikel personalisiertes Anfrageformular.
Und zu guter Letzt möchten wir Sie bitten, den Artikel zu bewerten. Damit helfen Sie uns, die Qualität der Artikel zu verbessern - und anderen Lesern bei der Auswahl der Artikel, die sie lesen sollten.
©2000-2006 AspHeute.com |