# Zugriff auf Filter Servlet



## robsc (15. Okt 2007)

Hallo,
ich nutze für eine Web-Anwendung einen Authentication Filter Servlet. Eine Instanz davon wird bei Start des Tomcat Servers angelegt. 
Nun können die Berechtigungen aus der Webanwendungen heraus geändert werden, dazu ist jedoch ein Aktualisieren des Filters nötig.

Wie kann ich auf das Filterobjekt  zugreifen?
Oder alternativ wie lässt sich der Server aus der Anwendung heraus neustarten?


----------



## maki (15. Okt 2007)

An dieser Stelle wäre es wirklich gut wenn du uns sagen würdest was genau dein Servlet macht (Quelltext).



> Oder alternativ wie lässt sich der Server aus der Anwendung heraus neustarten?


Der Server lässt sich nicht aus der Anwendung neu starten, denn der Server startet deine Anwendung...


----------



## robsc (15. Okt 2007)

Die Seiten und die darauf berechtigten Rollen werden im mom im Konstruktor ausgelesen (einmal beim Start der Anwendung)

```
public AuthFilter()
	{
		// Zuordnung Seite-Rolle
		sites = new HashMap<String,List<String>>();
		
		List<WebPage> pages = new ArrayList<WebPage>();
		pages = pageDao.fetchAll();
		
		//Kontrollausgabe
		for (WebPage p : pages)
		{
			sites.put(p.name, p.getRequiredRoles());
		}
		
		publicSites = new ArrayList<String>();
		publicSites.add("/faces");
		publicSites.add("/login.jsp");
		publicSites.add("/logout.jsp");
	}
```

Bei jedem Zugriff werden diese überprüft, wenn ich hier aus der Datenbank auslese, hätte man immer die aktuellen Daten. 


```
public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException
	{
		
		// angeforderte Seite bestimmen
		String relativePath = ((HttpServletRequest) request).getServletPath();

		if (!publicSites.contains(relativePath))
		{
			// Session holen um Zugriff auf die UserBean zu erhalten
			Map<String, Object> session = FacesContext.getCurrentInstance().getExternalContext().getSessionMap();
			
			// UserBean aus der Session auslesen
			UserBean user = (UserBean) session.get("userBean");	
			
			if(user == null || !hasPermission(relativePath, user))
			{
				((HttpServletResponse) response).sendRedirect("login.jsp");
			}
			else
			{
				chain.doFilter(request, response);
			}
			
		}
		else
		{
			chain.doFilter(request, response);
		}
		
	}
```

Eigentlich reicht ein Aktualisieren durch den Admin nach einer Änderung, dh eine Methode refreshRoles() im Filter würde reichen. 
Nur habe ich keine Idee, wie ich so eine Methode aufrufen könnte.


----------



## y0dA (16. Okt 2007)

Der Filter, falls er als solcher in der faces.config sowie web.xml gekennzeichnet ist, wird doch ständig aufgerufen (wenn man forwarded) und da wird der Filter eh durchgearbeitet - verstehe dein Problem nicht wirklich.

Falls du meinst, dass deine Rollen aktualisiert gehören, dann kannst du ja eine Session Bean anlegen, in welche die Authentification Werte drinnstehen und demnach jene Bean im Filter ansprechen.


----------



## maki (16. Okt 2007)

Abgesehen davon, dass dein *Serlvet Filter* (nicht umgekehrt, denn das ist was anderes) anscheinend eine DB verbindung aufbaut,was als Designfehler gilt...

```
pages = pageDao.fetchAll();
```
könntest du doch dafür sorgen, dass die Daten neu gelesen werden, wenn die Daten sich geändert haben.

Ob die Daten sich geändert haben, könnte der Filter rausfinden, wenn zB. ein bestimmtes Context-Attribut gesetzt ist bzw. an dessen Wert.


----------



## robsc (16. Okt 2007)

hm das Halten der Daten in einer Session Bean wäre möglich, gefällt mir sehr gut. So kann ich die Datenbankanbindung dahin auslagern und dort die Aktualisierung anstoßen, wenn der Admin die benötigten Rollen ändert.

Natürlich würden die neuen Berechtigungen dann erst nach Start einer neuen Session vorliegen.


----------



## y0dA (16. Okt 2007)

robsc hat gesagt.:
			
		

> Natürlich würden die neuen Berechtigungen dann erst nach Start einer neuen Session vorliegen.



Wieso das?

+) Du hast einen Controller, nennen wir ihn "SessionUser", welcher die Rechte etc ändert/aktualisiert etc
--> Jenen solltest du benutzen um eben die Rechte zu ändern
+) Du hast ein Model "SessionUserModel", welches schlichtweg die aktuellen Rechte des Users beinhaltet und eben eine Session Bean sein sollte.
--> Wenn im Controller "SessionUser" nun eine Änderung der Rechte durchgeführt wird dann solltest du die entsprechenden Objekte in "SessionUserModel" anpassen

--> Guck dir mal MVC an


Oder verstehe ich dich schlichtweg falsch?
Meinst du folgendes Szenario:
Du hast eine Rolle User und eine Rolle Admin. Nur die Rolle Admin darf die Rechte verändern und demnach möchtest du, sobald jener die Rechte ändert dass der User die aktuellen Rechte bekommt (ohne vormaliges Logout und erst dann aktiv)? Wenn ja gäbe es hier auch die Möglichkeit dass du oben genannte SessionUserModel Klasse im Application Scope hälst, was Sinn ergibt.


----------



## robsc (17. Okt 2007)

Ja den zuletzt beschriebenen Fall wollte ich implementieren, sorry wenn ich mich unverständlich ausgedrückt hatte.
Nochmal wie ich es mir genau vorstelle: Jeder User hat eine Rolle. Der Admin kann für jede Seite festlegen welche Rollen auf diese Seite zugreifen dürfen, dies kann er über ein Webformular.
Die Daten des Users(auch Rolle) liegen in einer Session Bean.

Am Halten der erlaubten Rollen pro Seite in einer Bean mit Application-Scope arbeite ich gerade, wobei mir der Zugriff auf diese Application-Bean aus dem Filter nicht so recht gelingen will.


----------



## y0dA (17. Okt 2007)

Guten Morgen!
Auf die Beans kannst du im Filter nicht, wie jsf üblich, zugreifen, sondern musst dir das Objekt aus der session holen:

```
HttpServletRequest httpReq = (HttpServletRequest) req;
httpReq.getSession().getAttribute("beanName");
```

Wenn ich mich recht erinnere.


----------



## robsc (17. Okt 2007)

Hab jetzt das Problem, dass die Application-scoped Bean nicht angelegt wird, dh eine Testausgabe im Konstruktor wird nie aufgerufen.
Vermutung: Die Bean wird wohl von keiner jsf/jsp Seite benötigt und deswegen nicht aufgerufen.
Kann ich diese Bean manuell initialisieren?


----------



## robsc (17. Okt 2007)

Der Vollständigkeit halber:

```
FacesContext facesContext = FacesContext.getCurrentInstance();
			RolesBean roleBean = (RolesBean) facesContext.getApplication().createValueBinding("#{rolesBean}").getValue(facesContext);
```

Funktioniert nun, 

Vielen dank für eure Hilfe.


----------

