# [Struts] TilesRequestProcessor - processRoles



## clemson (9. Aug 2005)

Hallo!

Folgendes: Ich habe eine Applikation in Struts entwickelt, welche unter anderem mit verschiedenen Benutzer - sprich verschiedene Rollen - umgehen muss. Welche Rollen welche Action sehen dürfen, habe ich in der struts-config.xml festgelegt...


```
<action path="/admin"
	type="org.dea.odm.struts.actions.OdmForwardAction"
	roles="admin">
	<forward path="screen.admin" name="success" />
</action>
```

Neben dieser Rollenverarbeitung arbeite ich außerdom noch mit Tiles - aber das nur nebenbei erwähnt.

Die Rolle eines Benutzers - ein entsprechendes User-Objekt wird in der Session abgelegt - wird in einer Datenbank abgespeichert. Derzeit habe ich die Überprüfung, ob ein Benutzer eine benötigte Rolle besitzt, folgendermaßen implementiert:

den *TilesRequestProcessor*, und im speziellen die Methode *processRoles* übesrchrieben

```
protected boolean processRoles( HttpServletRequest request,
		HttpServletResponse response, ActionMapping mapping )
		throws IOException, ServletException {

	this.logger.log(Level.INFO, "processRoles");

	// get the role of the current user
	HttpSession session = request.getSession();
	Employee empl = (Employee) session.getAttribute(Constants.USER_SESS_KEY);
	String user_role = (String) session.getAttribute(Constants.USER_ROLE_SESS_KEY);

	// get the authorized roles for this action
	String[] roles = mapping.getRoleNames();
	StringBuffer tmp = new StringBuffer();
	for (int i = 0; i < roles.length; i++) {
		tmp.append("'");
		tmp.append(roles[i]);
		tmp.append("' - ");
	}
	this.logger.log(Level.INFO, "Authorized Roles: " + tmp.toString());

	// if there are no role or the length is less than 1, the user is
	// authorized
	if (null == roles || roles.length < 1) {
		this.logger.log(Level.INFO, "User '" + empl.getUsername()
				+ "' is authorized, because there are no roles!");
		return true;
	}

	for (int i = 0; i < roles.length; i++) {
		// if the user_role equals a quthorized role, the access is garanted
		if (roles[i].equals(user_role)) {
			this.logger.log(Level.INFO, "User '" + empl.getUsername()
					+ "' is authorized, because he has role '" + roles[i]
					+ "'");
			return true;
		}
	}

	this.logger.log(Level.INFO, "User '" + empl.getUsername()
			+ "' is NOT authorized, because he has the unauthorized role '"
			+ user_role + "'!");

	return false;
}
```

Wenn ein Benutzer eine bestimmte Rolle inne hat, so ist dieser berechtigt, diese Action auszuführen - klappt wunderbar.

Das Problem ist nur, dass ein unauthorisierter Benutzer, welcher eine für ihn nicht authorisierte Action ausführt, auf eine leere Seite weitergeleitet wird...

Quelltext dieser leeren Seite:

```
<html><body></body></html>
```

Meine Frage ist nun: wie bzw. wo kann ich festlegen, auf welche Seite ein unauthorisierter Benutzer weitergeleitet wird, wenn dieser eine nicht authorisierte Action ausführen will. Ich hätte es gerne folgendermaßen gelöst, dass der Benutzer anstatt dass er auf eine leere Seite geforwarded wird, auf eine Seite verwiesen wird, auf welcher eine Information steht, dass der Benutzer diese Rolle nicht besitzt...

Muss ich da irgendeinen globalen forward definieren?? oder kann ich das gar in der processRoles definieren??


----------



## clemson (9. Aug 2005)

Allgemeinere Frage: Wie würdet denn ihr eine Rollen-Verwaltung implementieren mittels Struts? Wohl auch über das roles-Attribut in der struts-config, oder?


----------



## KSG9|sebastian (10. Aug 2005)

clemson hat gesagt.:
			
		

> Meine Frage ist nun: wie bzw. wo kann ich festlegen, auf welche Seite ein unauthorisierter Benutzer weitergeleitet wird, wenn dieser eine nicht authorisierte Action ausführen will



Wie läuft die Steuerung ab ?

-> User klickt auf nen Link
-> Link geht gegen eine StrutsAction
-> Action wird verarbeitet
-> Mapping wird returned


Dann würde ich es so machen:

struts-config.xml

```
<action path="/admin" 
   type="org.dea.odm.struts.actions.OdmForwardAction" 
   roles="admin"> 
   <forward path="screen.admin" name="success" /> 
   <forward path="/WEB-INF/view/error.jsp" name="error"/>
</action>
```


ActionKlasse


```
public ActionForward execute(Action.......){
  if( hatRechte())
    return mapping.findForward("success");
  else
    return mapping.findFoward("error");
  
}
```


----------



## KSG9|sebastian (10. Aug 2005)

andere möglichkeit wäre noch folgende:


Du definierst dir eine Action die nur zum prüfen des Rechte da ist. In die Action packst du dann ein Forward für alle anderen Actions rein. Jeder Link den es gibt geht gegen diese ControllerAction und wird, wenn die Rechte vorhanden sind, zu der eigentlichen Action weitergeleitet.


----------



## clemson (10. Aug 2005)

diese möglichkeit habe ich mir auch schon gedacht. das problem ist nur, dass ich mehrere Action-Klassen besitze, und die Abfrage daher bei jeder Klasse machen müsste...

Dieses Problem habe ich folgendermaßen gelöst:


Ich habe eine Klasse *OdmAction*, welche von der Klasse *Action* des Struts-Pakets erbt

In der Methode *final execute(Mapping,Form,Request,Response)* der Klasse *OdmAction* wird die Überprüfung ausgeführt, ob der User die Rechte besitzt oder nicht. Besitzt dieser die Rechte, so wir die abstrakte Methode *executeAction* aufgerufen

Alle "wirklichen" Actions meiner Applikation erben nun von dieser Klasse *OdmAction*, und müssen daher auch die abstrakte Methode *executeAction* implementieren

Meine zweite Lösungsmöglichkeit wäre, die Rollen jeder Action, welche ein Benutzer besitzen muss, in der *struts-config.xml* bei den jeweiligen Actions zu definieren. Um zu überprüfen, ob ein User die vorhandene Rolle besitzt (welche in einer Datenbank gespeichert werden), muss ich die Methode *processRoles* des *TilesRequestProcessors* überschreiben...

Und da taucht mein Problem auf: Wenn der User die authorisierte Rolle nicht besitzt, so möchte ich, dass anstatt der internen Fehlerseite eine von mir festgelegte Fehlerseite angezeigt wird. Ich weiss allerdings nicht wie, denn die Methode *processRoles* hat als Rückgabetyp *boolean*, und wenn false zurückgegeben wird, so wird diese interne Fehlerseite angezeigt...


----------



## KSG9|sebastian (10. Aug 2005)

gibts nicht nen parameter in der struts config für ne error page bzw. für ne exception ?


----------



## clemson (10. Aug 2005)

hmm, ich könnte bei jeder einen exception parameter angeben...

aber gibt es auch eine möglichkeit, dass ich nicht bei jeder action diese definition machen muss, sondern ich eine globale exception definieren kann??


----------



## KSG9|sebastian (10. Aug 2005)

ja..google einfach mal oder schau dir von dem struts-mailreader die struts-config.xml an (die app bekomsmst du mit den sourcen von jetspeed2) www.apache.org/dist

unter

portals -> jetspeed2


----------



## odysseus (11. Aug 2005)

ich hab mit den roles in struts noch nicht getan, aber bevor Du in jede Action Klasse in der struts-config.xml ein und die selbe Exception deklarierst, solltest Du eine global exception deklarieren.


----------



## clemson (11. Aug 2005)

odysseus hat gesagt.:
			
		

> ich hab mit den roles in struts noch nicht getan, aber bevor Du in jede Action Klasse in der struts-config.xml ein und die selbe Exception deklarierst, solltest Du eine global exception deklarieren.



ja, das habe ich auch jetzt gemacht


----------



## clemson (11. Aug 2005)

Folgendes:

Ich habe mir eine Klasse *OdmExceptionHandler* definiert, welche von *ExceptionHandler* des apache pakets erbt. diesen odmexceptionhandler habe ich in meiner struts-config folgendermaßen eingetragen:


```
<global-exceptions>
	<exception type="java.lang.Exception"
		handler="org.dea.odm.struts.OdmExceptionHandler"
		key="exception.global"
		bundle="err" 
		scope="request"
		path="screen.error" />
</global-exceptions>
```

Wenn ich jetzt bei meinem *OdmRequestProcessor* in der Methode *processRoles* false zurückgebe, dann müsste doch eigentlich eine *UserIsNotAuthorizedException* von struts geworfen werden, und diese müsste dann von meinem *OdmExceptionHandler* behandlet werden, oder?? Tut sie aber nicht. Wisst ihr warum bzw. wo mein denkfehler liegt??


----------



## KSG9|sebastian (31. Aug 2005)

so geht es:


```
public boolean processRoles(HttpServletRequest request,
			HttpServletResponse response, ActionMapping mapping)
			throws IOException, ServletException {

		String[] roles = mapping.getRoleNames();
		
		for(int i=0; i<roles.length; i++){
			if(request.isUserInRole(roles[i]))
				return true;
		}
                                //default.do bringt den Benutzer wieder zurück zur Login-Seite
    
		request.getRequestDispatcher("/default.do").include(request, response);

		return false;

	}
```


----------



## clemson (31. Aug 2005)

aha! dann werde ich das mal gleich ändern...

dankeschön!


----------



## KSG9|sebastian (31. Aug 2005)

den RequestDispatcher kenn ich von Portlets..daher ist mir das jetzt erst eingefallenk, da ich auch ein paar Sachen mit Struts gemacht hab...


----------



## clemson (31. Aug 2005)

aha. jedenfalls funktioniert es jetzt


----------

