[Struts] TilesRequestProcessor - processRoles

Status
Nicht offen für weitere Antworten.

clemson

Bekanntes Mitglied
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...

Code:
<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
Code:
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:
Code:
<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??
 
Allgemeinere Frage: Wie würdet denn ihr eine Rollen-Verwaltung implementieren mittels Struts? Wohl auch über das roles-Attribut in der struts-config, oder?
 
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
Code:
<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

Code:
public ActionForward execute(Action.......){
  if( hatRechte())
    return mapping.findForward("success");
  else
    return mapping.findFoward("error");
  
}
 
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.
 
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...
 
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??
 
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.
 
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 😉
 
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:

Code:
<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??
 
so geht es:

Code:
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;

	}
 
den RequestDispatcher kenn ich von Portlets..daher ist mir das jetzt erst eingefallenk, da ich auch ein paar Sachen mit Struts gemacht hab... 😉
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben