Glengamoi (Forum) · AspHeute · .NET Heute (RSS-Suche) · AspxFiles (Wiki) · .NET Blogs
ASP German Homepage Homepage
 

Liste

.NET 2.0 (1)
.NET Allgemein (16)
.NET Fu (5)
ADO.NET (11)
Aprilscherz (3)
ASP Grundlagen (44)
ASP Tricks (83)
ASP.NET (44)
ASPIntranet.de (5)
C# (28)
Datenbank (44)
Dokumentation (4)
IIS 6.0 (1)
Komponenten (29)
Optimierung (10)
Server (21)
Sicherheit (34)
Tee Off (6)
VB.NET (6)
WAP (8)
Web Services (11)
XML (9)

RSS 2.0 - Die neuesten fünf Artikel auf AspHeute.com


 

Suchen





 

English Articles
Chinese Articles
Unsere Autoren
 
Link zu AspHeute
Impressum
Werben
Anfragen

ASP-basierte Basic Authentication

Geschrieben von: Christoph Wille
Kategorie: Sicherheit

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 Authentication

Der 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 Implementierung

Zuerst 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ßbemerkung

Mit 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 Codes

Klicken Sie hier, um den Download zu starten.

Verwandte Artikel

Erstellen eines HTTP Test Tools
Formular-basierte Basic Authentication
Generieren eines sicheren Paßwortes
Passwörter mit SHA1 absichern
Verwendung von SSL Test-Certificates
Verzeichnissicherheit mit NTFS und IIS Authentifizierung

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.

Bewerten Sie diesen Artikel
 Sehr gut   Nicht genügend  
   1  2  3  4  5  
 

  
   Für Ausdruck optimierte Seite

©2000-2006 AspHeute.com
Alle Rechte vorbehalten. Der Inhalt dieser Seiten ist urheberrechtlich geschützt.
Eine Übernahme von Texten (auch nur auszugsweise) oder Graphiken bedarf unserer schriftlichen Zustimmung.