Struts2 e Tiles2: esempio di logging tramite interceptor

Scarica il progetto di esempio (Eclipse Helios)

Questo è un esempio di come si può definire la fase di autenticazione e di controllo dell’autenticazione stessa tramite un interceptor. L’interceptor che andrò a definire farà queste cose:

- verifica che nella sessione sia presente un oggetto UTENTE
- se non è presente verifica che la navigazione provenga dalla pagina di login.
- se si proviene dalla pagina di login controlla utente/password e li autentica
- in tutti gli altri altri casi redirige alla pagina di login

Tutto questo avviene prima della visita di ogni pagina, proprio per la definizione stessa di interceptor. Ecco come può essere il metodo intercept dell’interceptor:

public String intercept (ActionInvocation invocation) throws Exception {
 
	// Dall'action context ho accesso agli oggetto request e quindi session
    final ActionContext context = invocation.getInvocationContext ();
    HttpServletRequest request = (HttpServletRequest) context.get(StrutsStatics.HTTP_REQUEST);
    HttpSession session =  request.getSession (true);
 
    // Se nella sessione c'è un oggetto chiamato "UTENTE" sognifica che sono già loggato
    Object user = session.getAttribute ("UTENTE");
    if (user == null) {
 
    	// Non c'è nessun utente autenticato. Per verificare se provengo dalla form di login, verifico che ci sia un parametro
    	// "login" nella request e che sia diverso dalla stringa vuota.
 
        // Verifico di stare provenendo dalla form login
        String login = request.getParameter ("login") != null ? request.getParameter ("login").toString() : "";
        if (! login.equals("") ) { // L'utente sta cercando di loggarsi.
 
    		String request_user = request.getParameter ("USERNAME") != null ? request.getParameter ("USERNAME").toString() : "";
    		String request_password = request.getParameter ("PASSWORD") != null ? request.getParameter ("PASSWORD").toString() : "";
 
    		boolean autenticato = false;
    		Personaggio utente = null;
    		// Qui dovrà esserci una vera autenticazione
    		if ("paperino".equals(request_user) && "paperino".equals(request_password)) {  
    			utente = new Personaggio("Paperino", new String[]{"Cioccolata","Sigarette"});
    			autenticato = true;
    	    }
    	    else if ("pippo".equals(request_user) && "pippo".equals(request_password)) {  
    			utente = new Personaggio("pippo", new String[]{"Noccioline","Fiches"});
    			autenticato = true;
    	    }	    		
 
    		if (autenticato) {
    			// Se sono autenticato salvo nella sessione l'oggetto UTENTE
	        	session.setAttribute("UTENTE", utente);
    			return "login-success";		        	
    		} else // Non sono autenticato, rimango nella login
    			return "login";
        }
 
        // Se sono arrivato qui significa che non provenivo dalla form di login
        return "login";
    } else { // Sono già loggato, lascio passare 
        return invocation.invoke ();
    }
}

In questo esempio, se non sono già autenticato e l’autenticazione va a buon fine, creo un mio oggetto Personaggio, lo instanzio e lo metto nella sessione. Da questo punto in poi, ogni volta che l’interceptor verrà chiamato, mi lascerà passare senza fare nulla.

Nel file struts.xml vado a dichiarare il nuovo interceptor, e ad appenderlo allo stack standard. Utilizzo anche due global result, login e login-success, che vengo chiamati in caso di non autenticazione e di autenticazione avvenuta con successo:

<package name="default" extends="struts-default" namespace="/">
	<result-types>
		<result-type name="tiles"
			class="org.apache.struts2.views.tiles.TilesResult" />
	</result-types>
 
	<!-- 
		Questa è la sezione dedicata agli interceptor  
	-->  
	<interceptors>
 
		<!-- 
			Definisco l'interceptor login 
		-->
		<interceptor name="login"
			class="topolinia.interceptors.LoginInterceptor" />
 
		<!-- 
			Creo uno stack di interceptor semplicemente aggiungendo
			a quello di default il mio 
		-->
		<interceptor-stack name="defaultLoginStack">
			<interceptor-ref name="defaultStack" />
			<interceptor-ref name="login" />
		</interceptor-stack>
 
	</interceptors>
 
	<!--
		Tutte le action utilizzeranno di default il mio nuovo stack,
		a meno che non sia specificato diversamente nella loro definizione
	-->
	<default-interceptor-ref name="defaultLoginStack" />
 
	<!-- L'aciont di default in caso di errore -->
	<default-action-ref name="index" />
 
	<!-- 
		Questi due global result vengono chiamati dall'interceptor che
		effettua il login	
	 -->
	<global-results>
		<result type="tiles" name="login">login</result>
		<result type="redirectAction" name="login-success">index</result>
	</global-results>
 
	<action name="index" class="topolinia.action.Topolinia" method="home">
		<result type="tiles">home</result>
	</action>
 
	<action name="logout" class="topolinia.action.Topolinia" method="logout">
		<result type="tiles" name="success">login</result>
	</action>
 
</package>

Tralasciando il fatto che utilizzo tiles2, e che quindi il global-result login è definito nel file tiles.xml, la pagina di login avrà un campo hidden di nome “login”, che serve all’interceptor per capire se stiamo venendo proprio da questa pagina:

<%@ taglib prefix="s" uri="/struts-tags"%>
 
<form action="index" method="post" >
	<s:hidden name="login" value="%{'1'}" />
	<s:textfield name="USERNAME" id="USERNAME" label="Nome" />
	<s:textfield name="PASSWORD" id="PASSWORD" label="Password" />
	<s:submit value="Login" align="center" />
</form>

Da notare che non c’è nessuna action che li si chiama “login”, perchè è l’ìnterceptor che gestisce sia la parte di login che la parte di controllo, su ogni pagina visitata, della corretta autenticazione. In questo progetto di esempio è quindi l’action index quella che prima viene invocata nel caso di autenticazione avvenuta con successo.

Ho inserito anche una action per eseguire il logout, molto semplice, che non fa altro che invalidare la sessione:

public String logout() throws Exception {
 
	HttpSession session = request.getSession();
	session.invalidate();		
 
	return SUCCESS;
}

Scarica il progetto di esempio (Eclipse Helios)

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>