jueves, 12 de julio de 2012

Control de sesiones con Struts y Spring II

 

Esta entrada es continuación de Control de sesiones con Struts y Spring I es necesario leer la primera entrada para entender la actual.

Resumiendo muy brevemente, el uso token para struts.

El token permite ejecutar una acción una única vez, asociando una marca única asociada a una acción. La marca solo se actualizara una vez finalizada la acción en ejecución.

La utilización del token va a permitir que dentro de un navegador, se evite la ejecución de acciones desde diferentes ventanas o pestañas.

Aspectos a tener en cuenta a la hora de utilizar el token de struts y querer controlar todas las acciones dentro de la aplicación.

1.- Definir el interceptor correspondiente en struts.xml

   1: <interceptor-ref name="token"/>

2.- Peticiones por Post: Incluir la etiqueta <s:token/> en todos los formularios de la aplicación.


<s:form method="post" action="%{action2}" >
               <s:token/>



   1: <s:form method="post" action="EjemploSesionAction" >
   2:     <s:token/>
   3: </s:form>

3.- Peticiones por Get:


Definimos los enlaces de la siguiente forma:



   1: <s:url var="urlEjemplo" action="ejemploAction">  
   2:     <s:param name="struts.token.name">struts.token</s:param>
   3:     <s:param name="struts.token"><s:property value="struts.token"/></s:param> 
   4: </s:url>
   5: <s:a href="%{urlEjemplo}" id="ejemploAction">
   6:    <s:text name="ejemplo.sesion.enlace"
   7: &lt;/s:a>

 


4.- Problemas por RedirectAction y perdida de token:


Creamos una clase BaseAction extensible por todas las clases que ejecutan Action de la aplicación. Esta clase tendrá el parámetro “tokenRedirect” y el método getTokenRedirect.



   1: package net.ejemplo.sesiones.action;
   2:  
   3: import com.opensymphony.xwork2.ActionSupport;
   4: import org.apache.struts2.util.TokenHelper;
   5:  
   6: /**
   7:  *
   8:  * @author terinventer
   9:  */
  10: public class BaseAction extends ActionSupport {
  11:  
  12:     static final long serialVersionUID = 1l;
  13:     private String tokenRedirect;
  14:  
  15:     public BaseAction() {
  16:     }
  17:  
  18:     @Override
  19:     public String execute() throws Exception {
  20:         return SUCCESS;
  21:     }
  22:  
  23:  
  24:  
  25:     public String getTokenRedirect() {
  26:         
  27:        /**
  28:         * Actualizar el token para el action redirect.
  29:         */
  30:         String tokenAux = TokenHelper.generateGUID();
  31:         try {
  32:             session.put("struts.token", tokenAux);
  33:         } catch (IllegalStateException e) {
  34:             String msg = "Error creating HttpSession due response is commited to client. You can use the CreateSessionInterceptor or create the HttpSession from your action before the result is rendered to the client: " + e.getMessage();
  35:             LOG.error(msg, e);
  36:             throw new IllegalArgumentException(msg);
  37:         }
  38:         
  39:         tokenRedirect = tokenAux;
  40:         return tokenRedirect;
  41:     }
  42:  
  43:     public void setTokenRedirect(String tokenRedirect) {
  44:         this.tokenRedirect = tokenRedirect;
  45:     }
  46: }

 


Tras esto, es necesario definir los redirect de la siguiente forma en struts.xml.



   1: <result type="redirectAction" name ="ejemploRedirect">
   2:     <param name="actionName">actionRedirect</param>
   3:     <param name="struts.token.name">struts.token</param>
   4:     <param name="struts.token">${tokenRedirect}</param>
   5: </result>

 


5.- Result <result type="stream">, Si queremos evitar perder el token a la hora de descargar un fichero utilizando este tipo de resultado para struts. Existe la opción de realizar la descarga mediante el uso de un iFrame oculto.



   1: <action name="Download" class="net.ejemplo.sesiones.action.DownloadAction">
   2:     <result type="stream">
   3:         <param name="contentType">contentType</param>
   4:         <param name="inputName">inputName</param>
   5:         <param name="contentDisposition">contentDisposition</param>
   6:         <param name="contentLength">contentLength</param>
   7:         <param name="bufferSize">1024</param>
   8:     </result>
   9: </action>

 


En la pagina sería necesario invocar a este action mediante la utilización de js.



   1: <script type="text/javascript">
   1:  
   2:     var elemIF = document.createElement("iframe");
   3:     elemIF.src = "Download.action";
   4:     elemIF.style.display = "none";
   5:     document.body.appendChild(elemIF);
</script>

Esto hará que se habrá el dialogo de descarga sin perder el correspondiente token.


 


Con todos estos aspectos, en principio tendríamos controlada la sesión de un usuario.


Como dije es una opción entre muchas, puede ser que falte algún aspecto que tratar.


El código fuente del proyecto se puede encontrar en código fuente o descargar pulsando el botón download.


 


Espero vuestras opiniones y comentarios.


Saludos

No hay comentarios:

Publicar un comentario