# Zugriff auf geschützten Bereich ohne Authentifizierung



## Raphalon (29. Jul 2011)

Hallo,

ich verwende für eine JSF - Anwendung container managed security - CMS (Umgebung: glassfish 3.1, eclipse). Dabei wird eine index.html aufgerufen, welche einen Link auf eine JSF - Datei in einem geschützten Bereich enthält. Diese soll die Daten einer UserBean anzeigen (welche in login.html eingegeben wurden). Aufgrund der CMS wird bei Aufruf des Links in index.html automatisch eine login.html angezeigt. Nach Eingabe der Authentifizierungsdaten wird dann auf welcome.xhtml im geschützten Bereich weitergeleitet. 

Nun habe ich eine Logout-Funktion in der UserBean geschrieben, welche den security session beendet (session.invalidate()) und einen redirect auf die index.html macht.

*Problem*: Wenn man ausloggt und wieder auf der index.html landet, und anschließend wieder auf den Link in den geschützten Bereich klickt, wird nicht die login.html angezeigt, sondern direkt die welcome.xhtml des geschützten Bereichs. Dabei ist zwar die Bean dahinter (welche die Daten für die Anzeige in welcome.xhtml enthält) leer, aber warum wird nicht direkt die login.html angezeigt?

Ich bekomme beim Start der Anwendung eine "_WARNUNG: JSF1015: Anforderungspfad '/faces/protected/welcome.xhtml' beginnt mit einem oder mehreren Vorkommen der FacesServlet-Präfix-Pfad-Zuordnung '/faces'._", aber wenn im Link von index.html das faces weglasse, dann wird welcome.xhtml ja nicht als JSF-Seite interpretiert.

*Wie kann ich den Logout machen, so daß man nicht mehr in den geschützten Bereich kommt? Geht das durh eine Änderung der Konfiguration oder Programmierung?*


index.html


```
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Start page</title>
</head>
<body>
<p>Click <a href="faces/protected/welcome.xhtml">this link</a> to access protected
information.</p>
<p><a href="faces/adminarea/change.xhtml">admin area</a></p>
</body>
</html>
```
web.xml

[XML]<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
         http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">
	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>/faces/*</url-pattern>
	</servlet-mapping>
	<welcome-file-list>
		<welcome-file>index.html</welcome-file>
	</welcome-file-list>
	<context-param>
		<param-name>javax.faces.PROJECT_STAGE</param-name>
		<param-value>Development</param-value>
	</context-param>

	<security-constraint>
		<web-resource-collection>
			<web-resource-name>Protected Pages</web-resource-name>
			<url-pattern>/faces/protected/*</url-pattern>
			<url-pattern>/protected/*</url-pattern>
		</web-resource-collection>
		<auth-constraint>
			<role-name>alloweduser</role-name>
		</auth-constraint>
	</security-constraint>

	<login-config>
		<auth-method>FORM</auth-method>
		<realm-name>LoginContainerRealm</realm-name>
		<form-login-config>
			<form-login-page>/login.html</form-login-page>
			<form-error-page>/errorpages/noauth.html</form-error-page>
		</form-login-config>
	</login-config>

	<security-role>
		<role-name>alloweduser</role-name>
	</security-role>
</web-app>[/XML]

faces-config.xml

[XML]<?xml version="1.0" encoding="UTF-8"?>

<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
	version="2.0">
	<navigation-rule>
		<from-view-id>/protected/welcome.xhtml</from-view-id>
		<navigation-case>
			<from-outcome>logout</from-outcome>
			<to-view-id>/index.html</to-view-id>
			<redirect />
		</navigation-case>
	</navigation-rule>
</faces-config>[/XML]


UserBean


```
@Named("user")
@SessionScoped
public class UserBean implements Serializable {
	
	final static Logger logger = Logger.getLogger(UserBean.class);
	
	private String name;
	private String role;

	public String getName() {
		if (name == null)
			getUserData();
		return name == null ? "" : name;
	}

	public String getRole() {
		return role == null ? "" : role;
	}

	public void setRole(String newValue) {
		role = newValue;
	}

	public boolean isInRole() {
		ExternalContext context = FacesContext.getCurrentInstance()
				.getExternalContext();
		Object requestObject = context.getRequest();
		if (!(requestObject instanceof HttpServletRequest)) {
			return false;
		}
		HttpServletRequest request = (HttpServletRequest) requestObject;
		return request.isUserInRole(role);
	}

	private void getUserData() {
		ExternalContext context = FacesContext.getCurrentInstance()
				.getExternalContext();
		Object requestObject = context.getRequest();
		if (!(requestObject instanceof HttpServletRequest)) {
			return "error";
		}
		HttpServletRequest request = (HttpServletRequest) requestObject;
		name = request.getRemoteUser();
	}
	
	public String logout() {
		ExternalContext context = FacesContext.getCurrentInstance()
				.getExternalContext();
		Object sessionObject = context.getSession(false);
		if (!(sessionObject instanceof HttpSession)) {
			return "error";
		}
		HttpSession session = (HttpSession) sessionObject;
		session.invalidate();
		return "logout";
	}
}
```


welcome.xhtml

[XML]<h:body>
   <h:form>
         <hutputText value="#{user.name}" />
         <hutputText value="#{user.inRole}" />
   </h:form>
</h:body>
</html>[/XML]

Danke,

Raphalon


----------



## nocturne (31. Jul 2011)

Könnte es sein, dass die ManagedBean den Scope "Application", anstatt "Session" hat?


----------



## Raphalon (31. Jul 2011)

Ja, die Bean hat die Annotation @SessionScoped und in der faces-config.xml ist nichts dazu konfiguriert.

Mittlerweile habe ich in einem JSF-Buch gelesen, daß es für container managed security gar keine Spezifikation zu einem logout gibt und man dazu den Browser beenden müsse. Kann das jemand bestätigen? Mir wäre in diesem Fall nämlich nicht ganz klar, wozu CMS gut sein soll.


----------



## nillehammer (1. Aug 2011)

> Kann das jemand bestätigen? Mir wäre in diesem Fall nämlich nicht ganz klar, wozu CMS gut sein soll.


Die CMS arbeited mit sog. Http-Headern. Wenn der Nutzer sich erfolgreich angemeldet hat, wird ein entspr. Header gesetzt, den der Browser nun bei jedem Request mit sendet. Damit das aufhöhrt must man tatsächlich den Browser schließen. Wenn Du den Firefox benutzt, kannst du Dir die Header mit Rechter Maustaste ->Seiteninformationen anzeigen lassen. Oder Du lädst Dir ein Addon z.B. Live-Headers herunter.

Gruß nillehammer


----------



## Raphalon (1. Aug 2011)

> Die CMS arbeited mit sog. Http-Headern. Wenn der Nutzer sich erfolgreich angemeldet hat, wird ein entspr. Header gesetzt, den der Browser nun bei jedem Request mit sendet. Damit das aufhöhrt must man tatsächlich den Browser schließen.


Vielen Dank! Weißt Du mir vielleicht noch eine Möglichkeit, wo ich das vertiefend nachlesen kann (Buch, www)? Im JavaEE Tutorial fandt ich dazu nichts.


----------



## nillehammer (1. Aug 2011)

> Vielen Dank! Weißt Du mir vielleicht noch eine Möglichkeit, wo ich das vertiefend nachlesen kann (Buch, www)? Im JavaEE Tutorial fandt ich dazu nichts.


Direkt nachvollziehen kannst Du es wie gesagt, indem Du Dir die Header einfach mal anschaust (siehe FF-Addons aus meinem vorherigen Post). Allgemein das Thema http-Authentication wird hier gut erklärt: HTTP-Authentifizierung ? Wikipedia
CMS unter Tomcat hier: Apache Tomcat 6.0 - Realm Configuration HOW-TO
Wobei dort nur steht, wie mans konfiguriert und nur in Nebensätzen, wie der Tomcat es dann umsetzt.


----------



## maki (1. Aug 2011)

Da wird aber FORM Authentifizierung verwendet, nicht BASIC HTTP, somit würden auch kein Authorization Header verwendet, den nutzt nur BASIC.

Sicher dass die Session invalidiert wird beim Logout oder bleibt sie bestehen?


----------



## nillehammer (1. Aug 2011)

Richtig! In der web.xml steht's ja! Ich hatte mich von dem "der Browser muss geschlossen werden" in die Irre leiten lassen. *Jetzt* hab ich mir den Code nochmal gründlich angeschaut. Einen Fehler hab ich nicht entdecken können. Als mögliche Ursachen fallen mir nur zwei Sachen ein:
-Wie Maki schon sagt, wird die Session nicht invalidiert. Obwohl der Code so aussieht, als müsste das eigentlich passen.
-Der Browser hat die Seite /protected/welcome.xhtml in seinem Cache und wenn Du den Link klickst siehst due den Inhalt des Cache und der Request geht garnicht zum Server


----------



## Raphalon (2. Aug 2011)

maki hat gesagt.:


> Sicher dass die Session invalidiert wird beim Logout oder bleibt sie bestehen?


Wie kann ich das überprüfen?



nillehammer hat gesagt.:


> Der Browser hat die Seite /protected/welcome.xhtml in seinem Cache und wenn Du den Link klickst siehst due den Inhalt des Cache und der Request geht garnicht zum Server


Ich habe den Cache deaktiviert. Das TCP/IP-Monitoring des glassfish zeigt auch, daß die Datei vom Server neu geliefert wird. 

Also doch möglicherweise das nicht funktionierende logout. Kann es sein, daß das möglicherweise gar nicht geht, weil nicht "spezifiert" für das CMS? 
Wie gesagt, bei "core JAVASERVER (TM) FACES, THIRD EDITION von DAVID GEARY und CAY HORSTMANN steht: "_NOTE: Currently, there is no specification for logging off or for switching identities when using container-managed security. This is a problem, particularly for testing web applications._" Man müsse zum Wechsel des Users immer den Browser neu starten.


----------



## nillehammer (2. Aug 2011)

Also wie gesagt, glaube ich, dass Dein Code funktionieren müsste. Debugging oder Logging in Deinem Code macht deswegen glaube ich keinen Sinn. Ich schlage folgendes vor: Aktiviere die Manager-Applikation des Tomcat (Apache Tomcat 6.0 - Manager App HOW-TO). Dort kann man sich alle aktiven Sessions je Webapplikation auflisten lassen und es ist auch sonst ein sehr nützliches Tool.
-Rufe diese Liste auf, sie müsste leer sein.
-Logge Dich in deine Anwendung ein.
-Refreshe die Session-Liste. Es müsste jetzt eine Session auftauchen. Du kannst die Id mit dem Wert des Cookies vergleichen, um sicher zu gehen, dass Du die richtite Session siehst.
-Logge Dich aus Deiner Anwendung aus.
-Refreshe die Session-Liste. Sie müsste jetzt wieder leer sein.
Falls nicht, hat in Deinem Code das invalidate nicht funktioniert.


----------



## akimoon (3. Aug 2011)

hm.. kann es dabei aber nicht vorkommen, dass der Tomcat die Session noch gespeichert hat, obwohl der Browser schon längst geschlossen wurde? Ich glaub zumindest, dass ich so ein ähnliches Problem schonmal hatte..

eine einfachere möglichkeit wäre doch, den Session-Wert des Cookies auf der Seite ausgeben zu lassen, sich auszuloggen und dann wieder einzuloggen und dann zu überprüfen, ob sich der Wert verändert hat? Oder hab ich gerade irgendwo einen Denkfehler?


----------

