ASP-basierte Basic Authentication
Geschrieben von: Christoph Wille Die verschiedenen Authentifizierungsmethoden des IIS sollten zumindest grob bekannt sein: Integrated, Digest und Basic Authentication, absteigend gelistet nach ihrer sicherheitstechnischen Integration mit Windows NT. Alle haben eines gemeinsam - sie greifen für die Validierung der Benutzeraccounts auf NT Accounts durch. Heute wollen wir Basic Authentication dazu überreden, unsere von NT unabhängigen Accounts zu validieren. Wie funktioniert Basic Authentication?Relativ simpel, sodaß sich Basic Authentication in jedem am Markt befindlichen Browser wiederfindet - ein Vorteil, da man keine Benutzer ausschließt. Generell läuft es so ab: wenn der Client auf einen geschützten Bereich zugreift, so schickt der Server einen Authentication Request an den Client, dessen Header wie folgt aussehen könnten: HTTP/1.1 401 Unauthorized Server: Microsoft-IIS/5.0 Date: Sun, 20 May 2001 17:55:41 GMT WWW-Authenticate: BASIC Realm=AspHeute Secure Area Connection: Keep-Alive Content-Length: 16 Content-Type: text/html Set-Cookie: ASPSESSIONIDGQQQQJEC=OHPFICAALDHJBKBLJKBJCNKM; path=/ Cache-control: private Die interessanten Parts sind der HTTP Status Code in der ersten Zeile, als auch der Header WWW-Authenticate. Der Client weiß nun, daß er den Benutzer um Benutzername und Passwort fragen muß, und zeigt eine Dialogbox an: Diese Dialogbox dürfte nun wirklich so ziemlich jedem bekannt sein. Dort gibt man nun seinen Benutzernamen und Passwort ein, und der Browser versucht nun noch einmal, das Dokument vom Server zu requesten - dieses Mal jedoch mit Benutzernamen und Passwort im Request: HTTP_ACCEPT:image/gif, image/x-xbitmap, ... HTTP_ACCEPT_LANGUAGE:en-us HTTP_CONNECTION:Keep-Alive HTTP_HOST:localhost HTTP_USER_AGENT:Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0; .NET CLR 1.0.2901) HTTP_COOKIE:visit=4%2F19%2F2001+8%3A26%3A15+PM; ASPSESSIONIDGQQQQJEC=PHPFICAAPEOPKDBODDAOPICN HTTP_AUTHORIZATION:Basic YWRtaW46cHdk HTTP_ACCEPT_ENCODING:gzip, deflate Die hier gezeigten Header habe ich über ALL_HTTP erhalten. Der Header für den Account ist HTTP_AUTHORIZATION - allerdings könnte man die Daten (Benutzername und Passwort, grün markiert) als unlesbar bezeichnen. Wer jetzt glaubt, daß diese Daten verschlüsselt sind, ist leider schief gewickelt. Die Daten sind nur Base64 encodet, das hat mit Verschlüsselung leider nichts zu tun. Und das Decodieren könnte man sogar als Kinderspiel bezeichnen. Gut - wäre das jetzt Basic Authentication des IIS, würde jetzt der Account gegen die NT Accountdatenbank verglichen. Aber - wir wollen ja unsere Datenbank unterschieben, deshalb müssen einige Vorbereitungen getroffen werden. Voraussetzungen für ASP-basierte Basic AuthenticationDer wichtigste Punkt, den wir uns vor Augen führen müssen ist der, daß wir mittels ASP die Basic Authentication am IIS vorbei durchführen. Im Endeffekt führt der IIS immer nur anonyme Zugriffe durch, was im Unterschied bei "normaler" Basic Authentication nicht der Fall ist: dort werden die Zugriffe dann mit dem impersonierten Account durchgeführt. Die Authentifizierung des Clients wird bei "normalen" IIS Zugriffsmethoden per NTFS Zugriffberechtigungen "provoziert". Da wir die NTFS Berechtigungen nicht angreifen, müssen wir die Authentifizierung anders provozieren: wir müssen die 401er Fehler selbst generieren, und auch selbst abfangen, ohne daß uns der IIS mit seinen anderen Methoden in die Quere kommt. Eine davon ist Integrated Authentication. Diese sollte abgeschaltet werden, wie im folgenden Screenshot gezeigt: Jetzt sind wir "in charge", und können (beinahe) schalten und walten, wie wir wollen. Die ImplementierungZuerst möchte ich meine Site-Sicherheitsarchitektur vorstellen, bevor ich die Basic Authentication code. Da wir unsere Sicherheit selbst verwalten, müssen auch alle Seiten separat gesichert werden, sodaß niemand darauf Zugriff bekommt, der nicht eingeloggt ist. Dazu eignen sich Includes, die dann in die jeweiligen Dateien eingebunden werden können. Hier das Beispiel einer minimalen default.asp: <!-- #include file="securitycheck.asp"--> <html> <head><title>Secure Area</title></head> <body> Welcome 2 the secured area! </body> </html> Die wirklich interessante Datei ist somit securitycheck.asp: <% If Not Session("SecArea_LoginGranted") Then Session("IntendedTarget") = Request.ServerVariables("SCRIPT_NAME") & _ "?" & Request.ServerVariables("QUERY_STRING") Response.Redirect "login.asp" Response.End End If %> Falls der Benutzer nicht eingeloggt ist, wird er zur Datei login.asp umgeleitet. Allerdings speichere ich mir zuvor noch den aktuellen Dateinamen plus den QueryString, um den User nach erfolgreichem Login sofort zu seiner ursprünglich gewünschten Seite zurückschicken zu können. Nützlich, aber eigentlich auch nicht wirklich weltbewegend. Bleibt also nur login.asp, wo sich denn auch tatsächlich der interessante Code findet: <% Option Explicit Response.Buffer = True ' for iis 4.0 machines Const strThisRealm = "AspHeute Secure Area" Dim strUName, strPwd, strTargetPage GetAuthInfo strUName, strPwd If "" = strUName And "" = strPwd Then RequestAuthentication strThisRealm Response.End End If ' log in the user... here: hardcoded If "admin" = strUName And "pwd" = strPwd Then Session("SecArea_LoginGranted") = True strTargetPage = Session("IntendedTarget") ' check: no infinite loops please! If ("" = strTargetPage Or _ LCase(strTargetPage) = LCase(Request.ServerVariables("SCRIPT_NAME"))) Then strTargetPage = "default.asp" End If Response.Redirect strTargetPage Response.End Else RequestAuthentication strThisRealm Response.End End If %> Dieser Code ruft zwei Methoden auf, die ich später vorstelle: RequestAuthentication und GetAuthInfo. Erstere schickt den 401er Statuscode um die Authentifizierung zu provozieren, und letztere decodiert den HTTP_AUTHORIZATION Header und liefert Benutzernamen und Passwort. Der Login des Benutzers (If "adm...") ist mit Absicht hardcodiert - hier müssen Sie nur eine Funktion Ihrer Wahl aufrufen, um zB Benutzer anhand einer speziellen Datenbank zu validieren. Ich wollte es so allgemein und anpassbar wie möglich halten. Der im If-Block folgende Code setzt die benötigte Session-Loginvariable, und schickt den Benutzer dorthin zurück, von wo aus der Login verlangt wurde. Ich berücksichtige den QueryString, als auch mögliche Loops auf login.asp. Alles in allem ist es, ohne den Code der beiden noch vorenhaltenen Methoden, leicht verständlich wie der Prozess abläuft: beim ersten Request existieren noch kein Benutzername und Passwort, daher wird eine Authorization verlangt. Beim zweiten Aufruf existieren dann diese (hoffentlich), und der Benutzer wird mit der Benutzerdatenbank validiert. Existiert er, wird Einlaß gewährt. Ist er non-existent, wird eine weitere Autorisierung eingeleitet (Else Zweig). Als Abschluß nun die beiden Methoden, die die eigentliche Arbeit übernehmen: <!-- #include file="base64.asp" --> <script language="vbscript" runat="server"> Sub RequestAuthentication(ByVal strRealm) Response.Write "401 Unauthorized" Response.Status = "401 Unauthorized" Response.AddHeader "WWW-Authenticate","BASIC Realm=" & strRealm End Sub Sub GetAuthInfo(ByRef strUsername, ByRef strPassword) Dim strAuth, strUserPwdPortion, nPos strAuth = Request.ServerVariables("HTTP_AUTHORIZATION") strUsername = "" strPassword = "" ' Check for basic authentication If ("basic" = LCase(Left(strAuth, 5))) Then strUserPwdPortion = Base64decode(Mid(strAuth, 7)) nPos = InStr(strUserPwdPortion, ":") If nPos > 1 Then strUsername = Left(strUserPwdPortion, nPos - 1) strPassword = Mid(strUserPwdPortion, nPos + 1) End If End If End Sub </script> Die Funktionalität für Base64 Codierung und Decodierung habe ich in die Includedatei base64.asp verfrachtet. Verwendet wird Base64decode in der Funktion GetAuthInfo, bevor Benutzername und Passwort aus dem String herausgeparst werden können. Der Rest sind einfache Stringoperationen. Die Funktion RequestAuthentication ist noch einfacher gestrickt. Hier wird nur der Response Status verändert, und ein Header für die Authentifizierung gesetzt. Der Realm kann in login.asp durch die Konstante strThisRealm gesetzt werden, und scheint in der Dialogbox auf. Damit wären wir auch schon am Ende des Codes angelangt. Bis auf das Aufparsen von Base64 ist das benötigte ASP Wissen nicht als "Rocket Science" zu qualifizieren. SchlußbemerkungMit wenig Code und wenig Konfigurationsarbeit kann man Basic Authentication mittels ASP implementieren. Der Nachteil von Basic Authentication - keine Verschlüsselung der Accountdaten ohne SSL - bleibt aber leider dennoch bestehen. Download des CodesKlicken Sie hier, um den Download zu starten. Verwandte Artikel
Erstellen eines HTTP Test Tools 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. 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 |