# Komplette JSF-Webanwendung absichern



## ThePianoman (21. Sep 2011)

Hallo,

ich suche verzweifelt den Königsweg, um eine komplette Webanwendung abzusichern.
Es gibt tausende von Dokumenten zum Thema, aber ich sehe momentan den Wald
vor Bäumen nicht mehr. Daher bitte ich um etwas Orientierung. Vielleicht kann mir
jemand mit ein paar konkreten Beispielen weiterhelfen.

Fangen wir an: Ich habe eine Java-EE-6-Webanwendung (Glassfish) mit JSF 2.0 (Facelets), 
EJB, JPA und Servlets. Username, Passwort und 1 Rolle (nicht n Rollen) stehen in einer 
Datenbank, die per JNDI angesprochen wird. 
Der User loggt sich ein und soll abhängig von seiner Rolle bestimmte Seiten sehen
und andere eben nicht.

1. Ich will JSF-Seiten (*.xhtml) je nach Rolle sichtbar machen.
Bsp.: Admin darf erstelleUser.xhtml, loescheUser.xhtml, veraendereUser.xhtml sehen.
Angesteller darf zeigeUrlaub.xhtml und beantrageUrlaub.xhtml sehen.
Wenn der Angestellte per Eingabe in die Adresszeile "loescheUser.xhtml" (nicht erlaubt!)
eingibt, soll er auf die Login-Seite zurück (alternativ: Fehlerseite).

Hier will ich nicht in einer Konfig-Datei alle Rollen manuell und hartkodiert eingeben,
sondern wie gesagt die Datenbankeinträge (Tabelle "User" mit "Username", "Passwort", 
"Rolle", etc.) nutzen.

Wie gehe ich heutzutage da am besten vor? Ich will natürlich nicht in jeder Seite
<c:if test="!bean.isLoggedIn><gehe_zu_Fehlerseite></c:test>
schreiben, sondern das Ganze zentral konfigurieren.

Sind Filter zu empfehlen oder was anderes?

2. Die Servlet-Seiten sollen ebenso gesichert werden.

3. Ich habe mir JAAS angesehen und habe noch Probleme, den Nutzen zu verstehen.
Ist das noch "aktuell" bzw. sinnvoll für Webanwendungen?

4. Die Webanwendung hat auf den JSF-Seiten ein Richfaces-Menü, die abhängig 
von der Rolle des Nutzers anders aussieht. Ich muss also in JSF die Rolle mit Beans
abfragen. Wie passt das in eine integrierte Lösung rein, ohne viele unterschiedliche
Login-Klassen schreiben zu müssen.

5. Wenn die "Lösung" eine serverübergreifende Lösung wäre (hier: Glassfish UND Jboss
als Deploymentplattformen), wäre das super.

Vielen Dank schon mal,

Bernd


----------



## Sym (22. Sep 2011)

Hallo,

ja, JAAS ist sinnvoll.

Du kannst die meisten Dinge, die Du nutzen möchtest, in Deiner web.xml definieren. Damit ist die Umsetzung mit JAAS in der Regel serverunabhängig. Nur die Securitydomain musst Du in den entsprechenden Konfigurationen der Server setzen.

Z.B. kannst Du Areas bilden, die Dir für bestimmte Seiten Zugriff gewähren oder verbieten.


```
<security-constraint>
    <web-resource-collection>
        <web-resource-name>Admin Area</web-resource-name>
        <url-pattern>/faces/admin/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>Administrator</role-name>
    </auth-constraint>
  </security-constraint>
```
Damit wären alle Seiten unterhalb von /admin/ nur für die Rolle Administrator zugänglich.

Hier gibt es eine relativ gute Starthilfe, wie ich finde.

Zum Thema Datenbank gibt es für den JBoss folgende Hilfe für die Konfiguration. Zum Glassfish wird in dem vorherigen Link etwas gesagt.

Gruß


----------



## Nogothrim (22. Sep 2011)

> Wenn der Angestellte per Eingabe in die Adresszeile "loescheUser.xhtml" (nicht erlaubt!)
> eingibt, soll er auf die Login-Seite zurück (alternativ: Fehlerseite).



Das kann man z.B. mit einem JSF PhaseListener lösen, der bei jedem Request überprüft ob der User eingeloggt ist und wenn nicht einen redirect auf die login seite macht.


----------



## Sym (22. Sep 2011)

Nogothrim hat gesagt.:


> Das kann man z.B. mit einem JSF PhaseListener lösen, der bei jedem Request überprüft ob der User eingeloggt ist und wenn nicht einen redirect auf die login seite macht.


Wenn Du eine EE-Server Authentifizierung wie JAAS wählst, musst Du das nicht mehr selber bauen.


----------



## ThePianoman (22. Sep 2011)

@SYM: Besten Dank für den Link. Ich habe heute einen großen Teil des Tages
mit Sicherheit mit Sicherheit ;-) verbracht, habe auch - hoffe ich! - alles 
verstanden (Realms, Rollen, Request-Methoden zur Authentifizierung, Login-Bean 
für JSF, EJB-Schutz).

Aber eine Sache habe ich nicht zum Laufen gekriegt: die Übernahme der Nutzer-
daten mit den Rollen aus der Datenbank (JNDI) auf den Server. Dein Tutorial zeigt,
wie es gehen sollte, aber es klappt bei mir leider nicht: keine Exception, keine
Fehlermeldung weist mir den Weg.

Falls du da (vor mir ;-) ) was im Netz findest, nur her damit. Ich habe heute
mit dem JavaEE6-Tutorial von Oracle gearbeitet: puh, ist das schlecht ("Gehen
Sie jetzt auf Seite 300, dann auf Seite 900, dann wieder hier zurück...").

@Nogothrim: Danke für die Idee mit dem PhaseListener. Ich werde diesen nicht nehmen,
weiß aber jetzt, dass es ihn gibt.

Danke und Gruß
Bernd


----------



## nocturne (23. Sep 2011)

Es gibt noch etwas mehr, es gibt die mutual authentication, dabei stellt der server dem Benutzer anstatt einem passwort ein sicherheitszertifikat bereit das in den Webbrowser installiert werden muss.


----------



## Sym (23. Sep 2011)

nocturne hat gesagt.:


> Es gibt noch etwas mehr, es gibt die mutual authentication, dabei stellt der server dem Benutzer anstatt einem passwort ein sicherheitszertifikat bereit das in den Webbrowser installiert werden muss.


Da musst Du bei den Zertifikaten aber bei der Erzeugung aufpassen, welche Schlüssel du mitreichst. Das funktioniert natürlich nur, bei einem eingeschränkten Benutzerkreis, der keine Angst hat, ein Zertifikat zu installieren. 

Empfehlen kann ich das nicht.


----------



## TheDarkRose (23. Sep 2011)

Sym hat gesagt.:


> Empfehlen kann ich das nicht.


Gründe? Client-Zertfikat ist jedenfalls sicherer als Passwort.


----------



## Sym (23. Sep 2011)

TheDarkRose hat gesagt.:


> Gründe? Client-Zertfikat ist jedenfalls sicherer als Passwort.


Gründe:

- Es muss zusätzlich ein Zertifikat installiert werden, was Aufwand bedeutet, den nicht jeder Unwissende leisten kann
- Um "sichere" Zertifikate zu erzeugen, muss viel Know-How vorliegen, ansonsten ist das System wesentlich unsicherer als eine Name/Password-Authentifizierung
- Aufwand der Implementation ist wesentlich größer

Inwiefern ist das System sicherer. Oder anders gefragt, inwiefern ist ein Passwort (mit entsprechenden Anforderungen) unsicher? 

Und natürlich die Frage: Ist der Aufwand für die Entwicklung und den späteren Anwender berechtigt?

Da denke ich, dass dies in den meisten Fällen mit Nein zu beantworten ist.


----------



## ThePianoman (23. Sep 2011)

>Client-Zertfikat ist jedenfalls sicherer als Passwort.
In meiner Anwendung sollen neue Anwender vom "Manager" angelegt werden.
Auch wenn ich das wahrscheinlich nicht einbauen werde: kann man denn
"Zertifikate" für jeden neuen Anwender dynamisch erzeugen? Passt das auf
meinen Anwendungsfall?

Sorry, ich habe noch nicht gegoogelt. 

Gruß
Bernd


----------



## nocturne (24. Sep 2011)

Wie Sym schon sagt: Es ist etwas komplizierter.

Finanzierung:
Also StartCom mit StartSSL vergeben tatsächlich kostenlose Root-Zertifikate! Das ist absolut einzigartig! Dazu brauchst du zumindest eine Domain, im extremfall Reisepass, Lichtbild und Personalausweis. 

Zwischen Client-Zert und Server-Zert bestehen n-m relationen: 
Wenn ein neuer Benutzer ein Client-Zertifikat bekommt muss es im Server-Zertifikat registriert werden. Ebenso muss das Server-Zertifikat im Client-Zertifikat registriert werden. 

Ab dann ist die Authentifizierung und Verschlüsselung 100% rechtsverbindlich. Das Server-Zertifikat verweist auf den Rechtsvertretter (z.B. StartCom/StartSSL). 

Die Verbindung zum Server funktioniert technisch so:
Der Browser (Client genannt) geht auf index.html, der Server leitet weiter auf Port 443 und gibt sein Server-Zert-Hash an den Client, der Client sucht zum Hash passende Client-Zertifikate. Passt der Hash, die Domain und passt die Gültigkeitsdatum von Server-Zertifikat und Client-Zertifikat wird das Client-Zertifikat verschlüssselt zum Server hochgeladen. 
(Dieses Client-Zertifikat kann auch als E-Mail-Digitale-Unterschrift verwendet werden, verschlüsselt wird es aber erst mit Empfänger-Client-Zert)

Eine dynamische Erstellung ist durchaus machbar! 
Jedoch muss eigentlich jedes mal der Server neu gestartet werden, wenn ein Client-Zertifikat sich in das Server-Zertifkat registriert. Oder du hast zwei Java-Server und switcht sie im laufenden Betrieb (brauchst halt Session-Passivation und Session-Revocation und balancer).

Willst du das wirklich? Ich könnte dann mal ein YouTube-Video erstellen.


@DarkRose
Passwörter können im biologischen externen Speicher verwahrt werden. Dieser Vorteil besteht bei Client-Zertifikaten nicht! 
Meine Auftraggeber haben sich inzwischen Disketten (Floppys) zugelegt und leben damit sehr gut.


----------

