Freitag, 31. August 2012

Überlegungen zur Benutzeranmeldung in Web-Anwendungen

Wer eine Web-Anwendung mit PHP entwickelt, die nicht von jedem Internet-Benutzer anonym benutzt werden soll, muss überlegen, wie die Identität des Benutzers überprüft (Authentication) und der Zugriff gegebenenfalls abgelehnt werden kann.

Dafür gibt es zwei gängige Vorgehensweisen.Sie können in der Benutzeroberfläche der Anwendung einen Login-Dialog vorsehen und die Gültigkeit der Anmeldedaten in der Anwendung selbst prüfen oder Sie verwenden die sogenannte HTTP Authentifizierung. Beide Methode haben Vor- und Nachteile.

Eigener Login Dialog
 
Zur Anmeldung wird ein eigener Login-Dialog erzeugt. (Das GGF Framework, die "Contacts" Beispiel-Anwendung und die Gallery des ReinHTML Dialog Designers liefern dafür Vorlagen). Diese speichern per Konvention bei erfolgreicher Anmeldung den User-ID in einer der Variablen $_SESSION['userid']. Somit ist es möglich etwa Benutzer-spezifische Daten anhand der Benutzerkennung auszuwählen. Bei der Definition von Menüs oder Buttons, kann man angeben, dass sie deaktiviert sein sollen, solange kein Benutzer angemeldet ist (Funktion IsLoggedOn() in jeder Window-Klasse). Über eine logoff-Funktion kann einemAbmeldung explizit veranlasst werden. Sobald die PHP Session endet, endet natürlich ebenfalls die Anmeldung.

Natürlich muss man auch verhindern, dass der Login-Dialog einfach umgangen wird etwa indem jemand den URL eines Sub-Fensters manuell eingibt. (Im GGF-Framework wird das zuverlässig und vor allem automatisch verhindert). Der eingebaute Dispatcher lehnt alle URL's ab, die im jeweiligen Kontext nicht erlaubt bzw. sinnvoll sind. Damit ist es nicht möglich, dass der Login-Dialog umgangen und direkt "in die Mitte" einer Anwendung verzweigt wird.

Zu beachten ist, dass HTML Dialoge alle Daten (auch ein Passwort) im HTTP Protokoll unverschlüsselt übertragen. Anwendungen, die mit sensiblen Daten arbeiten sollten daher unbedingt das HTTPS Protokoll verwenden. Damit ist auch die Übertragung der Login-Daten gesichert.

Wie man etwa Apache für HTTPS einrichtet, ist etwa hier beschrieben. Web-Hoster bieten jedoch auch eigene, einfachere Varianten an.

HTTP Authentifizierung

Bei der HTTP Authentifzierung sorgt der Web-Server dafür, dass nur angemeldete Benutzer auf die
Dateien ihrer Anwendung zugreifen können. Beim Zugriff auf ein geschütztes Verzeichnis, fordert der Web-Server vom Client User-ID und Password an. Der Client, also der Web-Browser öffnet daraufhin einen eingebauten Standard-Dialog und fordert den Benutzer zum Login auf.

Der Web-Server prüft dann - nach vorkonfigurierten Methoden (Passwort-Datei, Datenbank Zugriff, LDAP Zugriff etc.) - ob die Anmeldedaten stimmen. Erst dann liefert er das Dokument an den Client aus bzw. führt Server-seitige Skripte (PHP) aus.

Welche Verzeichnisse am Web-Server auf diese Weise geschützt werden sollen und wie die Gültigkeitsprüfung von User-ID und Password erfolgen soll, wird in der Web-Server Konfiguration festgelegt. Die PHP Anwendung hat damit wenig zu tun. Allerdings wird der Name des angemeldeten Benutzers (und einige weitere Information) in der $_SERVER Variablen mitgegeben.

Damit der Benutzer nicht bei jedem Dateizugriff erneut um User-ID und Passwort gefragt werden muss, merkt sich der Web-Browser die Angaben und sendet sie automatisch an den Server wenn weitere Dateien vom Server angefragt werden. Im Normalfall werden User-ID und Passwort so lange gespeichert, bis das Browser-Fenster geschlossen wird. Fast immer bieten die Browser aber auch die Option an, die Information auch permanent in einem Passwort-Cache zu speichern. Das hat für den Benutzer den Vorteil, dass er beim Aufruf der Web-Anwendung seinen User-ID und sein Passwort nie mehr eingeben muß.

Das ist aber auch ein Nachteil. Wenn man seinen Arbeitsplatz verläßt ohne den Zugriff zu sperren, das Browser-Fenster zu schließen oder den Passwort-Cache zu leeren, kann jeder mit Zugang zum angemeldeten Rechner die Web-Anwendung öffnen ohne Userid und Passwort zu kennen, weil eben der Browser die Anmeldung automatisch durchführt. Deshalb verwendet man im Online-Banking die HTTP Authentication nicht. Leider gibt es auch keinen standardisierten Weg, von der Web-Anwendung aus ein Ausloggen des Benutzers zu veranlassen (also den Browser dazu zu bewegen eine Anmeldung zu "vergessen").

Gegenüber "Man-in-the-Middle" Angriffen bietet die HTTP Authentifizierung einen gewissen Schutz, sofern die Variante "Digest" Authentifizierung verwendet wird. Dabei sendet der Client das Passwort verschlüsselt an den Server. Ein "Abhören" der Anmeldedaten (etwa in einem offenen WLAN) wird damit zumindest wesentlich erschwert.

Allerdings sollten sensible Anwendungen ohnehin nur via HTTPS Ptotokoll betrieben werden, weil ja nicht nur das Passwort sondern auch die übertragenen Daten verschlüsselt werden müssen.

Möchte man die HTTP Authentifizierung im GGF Framework nutzen, so muss man  (ab Version 4.4) lediglich die Variable $http_authentication in GGFSetup.php auf TRUE setzen (Wie man den Web-Server konfiguriert, ist in der Datei GGFauthenticate.php beschrieben). Das bewirkt, dass nach erfolgreichem Login (wie bei Applikations-eigenen Login Dislogen) die Benutzerkennung in $_SESSION['userid'] gespeichert ist. Somit ist es auch in dieser Variante möglich etwa Benutzer-spezifische Daten anhand der Benutzerkennung auszuwählen.


Dienstag, 29. Mai 2012

Erste Schritte - Fenster und Dialoge


Ich denke in einer guten Anwendungsarchitektur sollte „Alles“ was zu einer Dialog-Seite gehört, in einer Klasse gekapselt sein.  Seiten in einer Web-Anwendung können wir in Anlehnung an gängige GUI Architekturen als Fenster betrachten.  Jede Fensterklasse ist für folgende Aufgaben verantwortlich:
  • Öffnen des Fensters: Generierung des HTML Codes zur Darstellung des Fensters im Browser. Befüllen der variablen Felder im Fenster mit den Ausgabedaten
  • Erkennen der  Benutzeraktionen im Fenster (Klick auf Buttons oder Menüs) und Aufruf von verknüpften Callback-Funktionen.
  • Übernahme der Eingabedaten sofern das Fenster Eingabefelder enthält.
  • Prüfung der eingegebenen Daten. Abspeicherung in einem Modell-Objekt.
Soweit so gut. Aber das ist noch nicht alles. Da Anwendungen im Allgemeinen aus mehr als einem Fenster bestehen, müssen Fenster auch Mechanismen anbieten, wie Daten von einem Fenster an ein anderes beim Öffnen übergeben werden und wie bei der Rückkehr von einem Sub-Fenster Ergebnisse übernommen und das aufrufende Fenster wiedereröffnet werden kann.

Da Web-Anwendungen immer auch Multi-User Anwendungen sind, müssen Fensterklassen auch in der Lage sein, sich in Benutzer-Sessions einzuklinken. Das heißt das Fenster muss zum Beispiel wissen, zu welchem Benutzer welche Eingabedaten gehören,  ob der Benutzer überhaupt angemeldet ist und wenn ja welche Rechte er hat.  

Es ist sinnvoll drei Arten von Fenstern zu unterscheiden:  Hauptfenster, nicht-modale Fenster und modale Fenster bzw. Dialoge. Das GGF Framework bietet jeweils eine Basisklasse dafür an.
  • Hauptfenster öffnen sich beim Start einer Anwendung. Sie müssen daher die Benutzer-Session initialisieren.
  • Modale Fenster bzw. Dialoge dienen zur Eingabe von Parametern zu einer Benutzeraktion. Um inkonsistente Zustände zu vermeiden, muss die Interaktion mit dem aufrufenden Fenster gesperrt werden solange der Dialog aktiv ist.
  • Nicht-modale Fenster hingegen können unabhängig voneinander  du auch mehrfach geöffnet werden.
Diese Mechanismen haben sich bewährt und werden seit bald 40 Jahren in GUI’s eingesetzt. Aus diesem Grund werden diese Entwurfsmuster auch vom GGF Framework und vom ReinHTML Dialog Designer für die Entwicklung von Web-Anwendungen unterstützt. Ein einfaches Beispiel für die Anwendung der Entwurfsmuster stellt die "Contacts" Anwendung dar. 

 
 
In den weiteren Posts werde ich Schritt für Schritt  beschreiben, wie eine solche Anwendung entwickelt werden kann. 

Freitag, 25. Mai 2012

Erste Schritte - Fenster und Klassen für interaktive Anwendungen

Schon vor vielen Jahren hat mich die Frage beschäftigt, inwieweit die Struktur transaktionsorientierter Systeme (damals ging es um CICS) mit den Prinzipien der objektorientierten Programmierung vereinbar ist. Die Antwort war: Es ist gar nicht so einfach strukturierte CICS Anwendungen zu entwickeln.

Heute haben wir HTML bzw. das HTTP Protokoll und wollen objektorientiert programmieren. Wieder stelle ich fest dass es gar nicht so einfach ist objektorientierte HTML Anwendungen zu erstellen. Im Grunde ist die Architektur von CICS sehr ähnlich der des HTTP Protokolls.
  1. Der Server schickt die Beschreibung einer Seite (damals hieß es Bildschirmmaske; heute ists ein HTML Dokument) zum Client. 
  2. Der Benutzer füllt Eingabefelder aus und drückt einen Button (damals wars ein physischer Knopf auf der Tastatur). 
  3. Der Client schickt einen Datenstrom zum Server. 
  4. Der Server startet ein Programm (damals hieß das CICS-Transaktion), das die Eingabedaten interpretiert und die nächste Seite (die nächste Maske, das nächste HTML Dokument) zum Client schickt (und alles beginnt von vorn).
Das Prinzip ist noch immer einfach und hat sich seit 1969 nicht geändert. Es ist vor allem für Systeme mit vielen Benutzern sehr effizient, wenn - anders als bei PC-Anwendungen, die auch im Hauptspeicher sitzen bleiben solange der Benutzer über seine Eingabe nachdenkt - die Verarbeitung nach dem Senden des HTML Dokuments abbricht, Speicher freigegeben wird und erst beim Einlangen des nächsten HTTP Requests (beim Klick auf einen Hyperlink oder einen Button) das Programm zur Verarbeitung gestartet wird.

Das Problem beginnt, wenn man darüber nachdenkt, dass die Definition einer Seite und die Verarbeitung der dort eingegebenen Daten logisch eng zusammen gehören. Die Interpretation von Eingabedaten hängt eben davon ab wo (in welchem Feld) sie eingegeben wurden. Und oft ist ja auch so, dass im nächsten Dialogschritt die gleiche Seite noch einmal angezeigt wird (z.B. mit neuen Daten oder zur Korrektur von Eingabefehlern).

Also will ich den Code zur Definition der Seite und zur Verarbeitung der Eingaben in einer Klasse und damit in einem File zusammenfassen. Mal ganz abgesehen von objektorientierten Grundsätzen, ist das Prinzip 1 Seite = 1 Klasse recht einfach zu verstehen und sorgt für Übersichtlichkeit in großen Systemen.

Wer Web-Anwendungen mit dem GGF Framework entwickelt, kann genau das tun.

Mittwoch, 23. Mai 2012

Erste Schritte - Vorbereitung

Wer interaktive Web-Anwendungen entwickeln möchte, die über ganz einfache Aufgaben wie Besucherzähler oder Formmailer hinausgehen (für diese gibt es fertige CGI Scripts) sollte sich zuerst einige Gedanken über die Architektur machen. Die Architektur, die grundlegende Struktur einer Anwendung, ist ein ganz entscheidender Faktor für Komplexität, Erweiterbarkeit und Wartbarkeit einer Anwendung.

Je größer und je langlebiger eine Anwendung werden soll, umso wichtiger ist es die richtige Architektur zu wählen. In diesem und den folgenden Beiträgen möchte ich einige Überlegungen darstellen, die der Entwicklung des ReinHTML Dialog Designers und des GGF Frameworks zugrunde liegen.

Die erste Architekturentscheidung dreht sich um die Frage, wo der Code der Web-Anwendung laufen soll. Sobald (gemeinsam genutzte) Datenbanken und/oder Sicherheit eine Rolle spielen kommt man um Server-seitige Programmierung nicht herum. Code, der am Client abläuft (Javascript) kann immer manipuliert werden und für zentrale Datenbanken ist eben ein Server nötig. Lösungen für die Anbindung der eigenen Programme an HTML Seiten am Web-Server gibt es viele. Eine Übersicht dazu findet man zum Beispiel hier. Schlussendlich geht es um die Frage:
  1. soll HTML und ausführbarer Code getrennt werden (Variante CGI, Perl), 
  2. soll ausführbarer Code in HTML Seiten eingebettet sein (z.B. ASP, JSP, HTML/PHP)  oder
  3. soll HTML dynamisch vom ausführbaren Code ezeugt werden (z.B. PHP) ? 
Wenn man nur ein wenig Dynamik in eine ansonsten statische Webseite hineinbringen möchte, dann ist die erste Variante kein schlechter Ansatz. Der zweite Ansatz ist eine Mischform, die Vorteile beim Durchsatz bieten kann, aber wie der erste Ansatz bei einer komplexen Anwendungslogik zu komplizierten, schlecht wartberen Systemen führen kann. Wenn man aber daran denkt, hauptsächlich Anwendungen zu programmieren und HTML nur als Beschreibungssprache für die Anwendungsoberfläche sieht, ist der dritte Ansatz am flexibelsten.

Es gibt also keine "beste" Variante zur Anbindung von Server-seitigem Code. Es hängt vielmehr von den Zielsetzungen ab.

Meine Zielsetzung bei der Entwicklung des GGF Frameworks war, eine Lösung herzustellen, die sich strikt an die Prinzipien der Objektorientierung hält und besonders die Entwicklung komplexer Anwendungen unterstützt. Das läßt sich meiner Ansicht nach am besten in Variante 3 realisieren. Ein wichtiges Prinzip ist dabei die Kapselung (encapsulation) von zusammengehörigem Code. Für interaktive Anwendungen heißt das zum Beispiel, dass der gesamte Code, der ein bestimmtes Dialogfenster realisiert, in einer Klasse zusammengefasst wird.

Sonntag, 13. Mai 2012

CSS basierte Drop-Down Menüs und viel mehr

Im letzten Post habe ich angekündigt über CSS-basierte Drop-Down Menüs zu schreiben. Nun hat es etwas länger gedauert als ursprünglich gedacht. Ich habe mich entschlossen zuerst die Version 1.0 des ReinHTML Dialog Designers online zu stellen. Mit dem Tool können Anwendungsfenster und Dialogformulare interaktiv erstellt werden.

Wie angekündigt, gibt es natürlich auch eine Lösung für Drop-Down und Flyout Menüs für insgesamt 4 (!) Menü-Ebenen. Das Beste daran: Die Lösung funktioniert auch für Internet Explorer (bis zurück zum IE6) für Firefox und für Safari (getestet am iPhone 4).

Ein einfaches Menü (2 Ebenen) kann zum Beispiel mit der Demo-Anwendung ausprobiert werden.

Das wichtigste aber: In der vorliegenden Version generiert der ReinHTML Dialog Designer nun nicht nur HTML Code, sondern auch PHP Code. Das bedeutet: Sie können mit dem Tool Fenster und Dialoge interaktiv entwerfen und dann Server-seitigen PHP Code generieren.

Es entsteht pro Fenster oder Dialog eine PHP Klasse, die folgendes enthält
  • PHP Code der das gesamte HTML zum Anzeigen des Fensters generiert
  • Verwaltung von persistenten Modellobjekten
  • Code zum Prüfen der Eingabedaten (Schutz gegen SQL Injection etc.) 
  • Code zum Befüllen der Ausgabefelder mit Daten aus den Modellobjekten
  • Code zum Einlesen der Modellobjekt-Daten von den Eingabedaten eines Formulars
  • Template-Code für Callback-Funktionen, die die Reaktion des Systems auf aktive Benutzeroberflächen-Elemente (Links, Buttons und - siehe oben - Menüs) implementieren. 
  • Funktionen zur Generierung von SQL für den Datenbank-Zugriff. 

Wie schon in der Betaversion für HTML, gilt nun auch für PHP:
  • Sie können die vom ReinHTML Dialog Designer generierten PHP Klassen auf den eigenen Rechner herunterladen, dann
  • manuell lokal weiterbearbeiten, ergänzen und testen und dann
  • wieder hinaufladen und das Layout des Fensters oder Dialogformulars interaktiv bearbeiten,
  • dann wieder herunterladen etc.
(echtes Roundtrip Engineering). Sie können sich sogar aus einer generierten HTML Version eine PHP Version erzeugen lassen und umgekehrt.

Das Ganze basiert auf einer mächtigen Anwendungsarchitektur, die von einem objektorientierten PHP Framework, dem GGF Framework, unterstützt wird. Damit lassen sich auch komplexe Web-Anwendungen zuverlässig implementieren. Der ReinHTML Dialog Designer selbst ist ein gutes Beispiel dafür. Er wurd emit dem GGF Framework und mit Hilfe früherer Versionen des Dialog Designers entwickelt.

Die Architektur von fertigen Anwendungen wird am Beispiel der Demo-Anwendung in einer ausführlichen Dokumentation (folgen Sie dem Link "Architecture" auf der GGF Framework Seite; derzeit nur auf Englisch, später werde ich auch eine Version auf Deutsch zur Verfügung stellen) erklärt. Auch der Quellcode der Demo-Anwendung steht zur Verfügung.

Ich hoffe, Sie finden das interessant. Über Ihr Feedback freue ich mich.

Dienstag, 13. März 2012

CSS Menüs in Web-Anwendungen

Im Internet findet man eine Reihe von Vorschlägen, wie man mit CSS auch ohne Javascript geschachtelte Menüs erzeugen kann, so wie wir sie vom Desktop kennen (vgl. http://meyerweb.com/eric/css/edge/menus/demo.html, http://csswizardry.com/2011/02/creating-a-pure-css-dropdown-menu/ oder http://nekkidblogger.com/2011/ultra-efficient-css-html-drop-menu-nekkidblogger-menu/ ). Wenn man allerdings damit eine Web-Anwendung entwickelt möchte, stößt man auf eine Reihe von Problemen.

Einige Lösungen setzen auf CSS3 Funktionen, die noch nicht von allen Browsern unterstützt werden. Es ist aber fatal, wenn das Menü nicht verwendet werden kann, weil Einträge nicht sichtbar sind.

Das Aufklappen von Dropdown- und Flyout-Menüs wird in allen Lösungen durch den "hover" Effekt ausgelöst. Dieser wird vom Mauszeiger ausgelöst. Wer keine Maus hat (Benutzer von Mobiltelefonen, Tablets) kann das Menü womöglich nicht bedienen. Dazu kommt, dass ältere Browser wie der Internet Explorer 6 hover-Effekte nur für den <a> Tag unterstützt. Man kommt dann für diesen Browser nicht ohne Javascript aus. Benutzer, die aus Sicherheitsgründen Skripte deaktiviert haben, können die Anwendung dann nicht bedienen.

Die Menüaktion wird durch einen Hyperlink ausgelöst. Das ist für statische Webseiten OK, aber in Web-Anwendungen unerwünscht, weil Benutzereingaben verloren gehen können.

Keine Menü-Lösung ohne Javascript möglich? Doch! Allerdings ist ein etwas anderer Lösungsansatz erforderlich. Darüber werde ich im nächsten Blog berichten.

Montag, 5. März 2012

Konzept für horizontales HTML Menü fertig

Wie zuletzt geschrieben, bin ich dabei ein HTML und CSS basiertes horizontales Menü mit Drop-Down Menüs und Flyout Menüs zu entwickeln, das so ähnlich aussieht, wie wir es von Desktop Anwendungen kennen. Trotz intensiven Nachforschungen im Netz konnte ich keine fertige Lösung dafür finden und habe nun eine Form entwickelt, die sowohl unter Firefox als auch im Internet-Explorer ansprechend aussieht.

Der nächste Schritt wird sein, die Lösung in den ReinHTML Dialog Designer einzubauen. Ein weiterer Baustein vom Betatest auf dem Weg zur Version 1.