Archivos del sitio javahispano

Preprocesado de peticiones SOAP en JAX-WS

Posteado por Félix García Borrego en May 25th, 2008

En el caso de que necesitemos establecer algún tipo de preprocesamiento/filtro/mecanismo de seguridad a un servicio web, una de las formas más interesantes es utilizando los manejadores HandlerChain que proporciona JAX-WS 2.x.

En primer lugar implementamos el manejador, que nos permitirá realizar procesamientos y postprocesamientos sobre las peticiones SOAP que lleguen a nuestro servicios web. Os dejo un ejemplo de un manejador que permite filtrar por ip:



public class SecurityServiceWebHandler  implements MessageHandler{

 private static Log log=LogFactory.getLog(SecurityServiceWebHandler.class);

 public Set getHeaders() {

 	return null;

 }

 public void close(MessageContext context) {

 }

 public boolean handleFault(MessageHandlerContext context) {

 	return true;

 }	/** Comprueba que las ips que acceden a la aplicación son efectivamente ip permitidas.

  * @see javax.xml.ws.handler.Handler#handleMessage(javax.xml.ws.handler.MessageContext)

  */

 public boolean handleMessage(MessageHandlerContext context) {

 	ServletRequest servletRequest = ((ServletRequest)context.get(MessageContext.SERVLET_REQUEST));

                // Obtenemos la ip remota que invoca al Servicio Web

 	String remoteAddres=servletRequest.getRemoteAddr();

 	String allowed=”192.168.10.160,80.58.0.12″;

 	if(StringUtils.contains(allowed, remoteAddres)){

 		if(log.isInfoEnabled())log.info(”Servicio Web solicitado desde ip: “+remoteAddres);

 	}else{

 		log.error(”Acceso denegado. La ip “+remoteAddres+” no tiene permiso para acceder a los WS.”);

 		throw new WebServiceException(”Acceso denegado. La ip “+remoteAddres+” no tiene permiso para acceder a los WS.”);

 	}

 	return true;

 }

}

Una vez implementado el manejador, lo siguiente es publicarlo en el fichero handlerchain.xml

<handler-chains xmlns=”http://java.sun.com/xml/ns/javaee”>
<handler-chain>
<handler>
<handler-class>org.viafirma.conector.security.SecurityServiceWebHandler</handler-class>
</handler>
</handler-chain>
</handler-chains>
El último paso es asociar nuestro servicio web con el manejador, mediante la anotación @HandlerChain.



@HandlerChain(file="handlerchain.xml")

@WebService(serviceName="ConectorFirmaRMIService",targetNamespace = "http://viafirma.org/client/", name = "ConectorFirmaRMIClient",portName="ConectorFirmaRMI",

endpointInterface = "org.viafirma.cliente.firma.rmi.FirmaClienteRMI")

public class ConectorFirmaRMI  extends UnicastRemoteObject implements FirmaClienteRMI {

Como ejemplo, gracias a este código podremos recuperar y registrar las ips de todas las peticiones entrantes a nuestro servicio web, y denegar las ips no admitidas.

Humor: El framewok perfecto

Posteado por Félix García Borrego en May 19th, 2008

Una de las claves del éxito de cualquier empresa de desarrollo es el framework sobre el que construye sus aplicaciones. En Viavansi, estamos muy implicados con este tema, y desde el departamento de I+D hemos desarrollado un potente framework, os dejo el diagrama de arquitectura:

Framework de trabaja de Viavansi

 

Firma electrónica y accesibilidad web

Posteado por Javier Echeverría Usua en May 10th, 2008

En las listas de AccesoWeb de SIDAR mantuvimos en 2005 una interesante discusión sobre la compatibilidad entre los puntos de verificación de accesibilidad de WAI y la firma electrónica, que requiere realizar procesos en cliente con tecnologías obviamente ejecutadas en cliente (Javascript + Applet Java o Active X). En tres años ha habido realmente poca evolución a este respecto, y considero que la discusión se puede mantener vigente.

Sobre la firma electrónica 

No confundamos firma electrónica con autenticación con certificado. Podemos acceder (login) a una aplicación web con nuestro certificado, y que sea accesible. En lo que se refiere a la firma electrónica en una aplicación web, hay sin embargo una serie de conceptos claros. El proceso técnico es más o menos como el que sigue (ahorrando varios pasos para no hacer un post tipo Biblia):

  1. El usuario introduce los datos que debe firmar. Esto puede ser de muchas formas; rellenar un formulario HTML, adjuntar un fichero, etc.
  2. El navegador del usuario debe generar un resumen (digest) con un algoritmo hash (tipo MD5 o SHA-1) de la información a firmar.
  3. El navegador debe utilizar la clave privada del certificado digital del cliente para encriptar esta información. Esta encriptación es simétrica; lo que se encripta con la clave privada podrá ser desencriptada con la clave pública, y sólo con esta. Para realizar esta operación, el navegador debe consultar de alguna forma el almacén de certificados del cliente, hacerle escoger el certificado con el que quiere firmar, y utilizar la clave privada almacenada en el certificado escogido para encriptar ese hash. Ya tenemos la firma: es el hash encriptado.
  4. El navegador envía al servidor de firma todos los datos necesarios: el hash encriptado y la clave pública del certificado digital del cliente. Ahora éste lo almacena con el formato que se considere más oportuno. En cualquier momento se puede verificar la validez de esa firma con una sencilla operación: desencriptando la firma con la clave pública del certificado, y comparándola con el resultado de realizar el hash Almacenar el documento original con su firma (el hash encriptado). De esta forma, si algún día se quiere comprobar que lo que introdujo el usuario (el documento original) no ha sido modificado maliciosamente (lo que le confiere validez legal), se puede realizar una sencilla operación de comprobación de firma, consistente en desencriptar la firma con la clave pública del certificado digital, obteniendo el hash, y aplicando el algoritmo de hash sobre el documento original. Si ambos hash coinciden, la firma es válida.

El problema es que los pasos 2 y 3 deben realizarse en cliente, es decir, en el navegador. Esto se totalmente necesario y obligatorio; precisamente, uno de los puntos clave para mantener la seguridad del proceso se basa en que la clave privada del certificado del cliente nunca sale de la máquina del cliente. Hay un número finito de tecnologías para ejecutar esto en un navegador web: lo más normal son applets Java (como el conocido OpenOCES, que utilizamos en Viafirma y que usan otras plataformas como la de Safelayer) o clientes Active X, invocados desde Javascript. De hecho, éste es uno de los puntos claves para que un trámite telemático sea lo más universal y usable posible: la calidad del componente cliente. Por ejemplo, la semana pasada tardé dos horas, experimentos en 3 máquinas diferentes (ya varios navegadores en cada una, aunque con Opera o Safari no llegas muy lejos) y un buen número de reinstalaciones de componentes para conseguir cambiar a mi mujer de médico de cabecera, debido a la infame calidad de los applets Java de firma de la plataforma @Firma. Si a mí me costó tanto, no quiero imaginar qué le ocurrirá a un usuario de a pie. El mayor problema es que funciona muy mal con el JRE Java 6, pero debería tenerse en cuenta que, salvo que se configure de forma diferente, el JRE se autoactualiza automáticamente, con lo que a estas alturas hasta el panadero de la esquina tiene instalado Java 6 en su máquina.

Sobre la accesibilidad web 

En lo que se refiere a la accesibilidad web, las pautas WAI te exigen que para acceder a tu contenido web no sea imprescindible el uso de applets o javascript. En concreto, la pauta 6.3 dice que “Asegúrese de que las páginas sigan siendo utilizables cuando se desconecten o no se soporten los scripts, applets u otros objetos programados. Si esto no es posible, proporcione información equivalente en una página alternativa accesible”.

Según esta pauta entendemos que no podemos tener una calificación AA de accesibilidad si utilizamos javascript y applets, ya que deberíamos tener una página alternativa. El problema es que no podemos tener una página alternativa ya que la operación que realizamos no se puede realizar de otra forma de forma legal.

Sobre las Administraciones Públicas 

Por último, las Administraciones Públicas exigen por regla general que sus portales web, incluyendo sus oficinas virtuales, alcancen un nivel AA de accesibilidad, esto es, cumplan todos los puntos de verificación de prioridad 1 y 2.

Pero también exigen que para que una operación telemática sea legal, se haga utilizando firma electrónica que, como hemos visto, tiene problemas insalvables de accesibilidad porque hoy por hoy no es posible firmar sin ejecutar lógica de cliente que no todos los navegadores o dispositivos de usuario tienen por qué soportar. Por ello, la alternativa legal que podemos dar a nuestra web con firma electrónica es que el usuario se vaya a la institución físicamente.

¿No es un contrasentido? Se piden dos cosas incompatibles entre sí.

Una conclusión: quedarse en medio.

Bajo mi punto de vista, no debemos olvidar que las pautas WAI se refieren al acceso al contenido. Una Oficina Virtual está mucho más cerca de una aplicación web que de un portal, por lo que debe plantearse si las pautas aplican con la misma restrictividad. En todo caso, siempre se puede tratar de que toda la web sea accesible realmente, y sacar la zona dotada de firma electrónica de la declaración de accesibilidad. Y esperar a que la tecnología avance para superar estos escollos.

Nosotros caminamos junto a hombres gigantes

Posteado por Félix García Borrego en April 27th, 2008

Hace 335 años Issac Newton utilizo la locución A hombros de gigantes en referencia a los grandes científicos que le habían precedido como Galileo, Kepler, Copérnico, Aristóteles : …si he podido ver más allá es estando parado sobre hombros de gigantes. Y no hay ninguna duda de que el avance de la Ciencia moderna se apoya en los científicos que les precedieron. En nuestro caso la Informática es demasiado joven para tener una verdadera historia y a pesar de eso ya tenemos mucho que agradecer a los gigantes sobre los que nos apoyamos.En nuestro trabajo, si además apostamos por el Software Libre tenemos que ser conscientes de que no solo nos apoyamos sobre hombros de gigantes sino que gracias al Software libre “Nosotros caminamos junto a hombres gigantes“…Sin buscar demasiado, todo nuestro entorno de desarrollo o cualquiera de nuestros proyectos le debe más al software libre de lo que nosotros jamas podamos retornar. A modo de ejemplo, dejo un pequeño listado de algunas de las librerías que aparecen en  los proyectos que hacemos en Viavansi, si uno hace cuentas, es fácil sentirse abrumado por la cantidad de código del que hacemos uso, y de lo mucho que tenemos que agradecer.

  • iText ( Bruno Lowagie), commons-lang (Daniel Rall, Stephen Colebourne,…), hibernate-annotations (Emmanuel Bernard,…), commons-beanutils (Robert Burrell Donkin, Craig McClanahan,…) , xalan (David Bertoni, John Gentilin, … ), commons-httpclient (Michael Becke, Jeff Dever, …), httpunit (Christian W. Hargraves, Kay Johansen, …), commons-fileupload ( Martin Cooper, John McNally,…), cglib (Juozas Baliuka , …), struts ( Craig R. McClanahan, Ted Husted, … ), dom4j (Curt Arnold, David White, … ), nekohtml( Andy Clark,… ), xml-security:xmlsec ( Derek Morr, Pete Hendry, …), jboss-javassist ( Shigeru Chiba,… ), xerces(Arnaud Le Hors, Tozawa Akihiko, …), hibernate-entitymanager ( Gavin King, …), commons-io (Serge Knystautas, …), net.openid:core (Jason Alexander, …), com.sun.facelets:jsf-facelets (Jacob Hookom, …), myfaces ( Ted Husted, …), bouncycastle (Tito Pena, …), …(1000s…)

Soy consciente de que me he dejado cientos de proyectos y miles de personas fuera de este listado, pero …Mil gracias a todos!

Viafirma.org 1.2.5

Posteado por Félix García Borrego en April 21st, 2008

Ya tenemos nueva versión de Viafirma (Nuestra plataforma de Firma y Autenticación Digital),  la lista completa de cambios es:

  • Migración del stack WebSerice utilizado, antes Xfire, ahora JAX-WS 2.1.
  • Nuevo método para el envío de emails firmados digitalmente.
  • Cache de CRLs para minimizar el número de accesos a CRLs externas.
  • Soporte de firma en servidor (indicando el alias y el password) y custodia de documentos firmados offline.
  • Actualizada la versión de la librería OpenId para el soporte completo de OpenId 1.1 y OpenId 2.0 (draft)
  • Mejorada la documentación de instalación y creada aplicación pre-empaquetada .war .
  • Añadido digito de control al identificador de firma.
  • Validación y recuperación de documentos custodiados mediante el identificador del documento.
  • Uso de friend-url para el acceso a documentos custodiados, ej:http://viafirma.viavansi.com/viafirma/v/Y1MW-9LE3-JE81-2087-8160-3774.
  • Mejorado el renderizado del QR-CODE, añadida información hash del documento y mejoradas en el formato de la etiqueta.
  • Mejorado el renderizado del justificante pdf, para formatos no A4.
  • Parametro para control de acceso al Servicio Web , ALLOWED=”ip,ip2″ indica que ips tienen permiso para acceder al servicio web.
  • Soporte de certificados almacenados en “Acceso a Llaves” de Mac OSX (Con esto ya tenemos soporte completo de Mac OS X).
  • Solución de bugs en el css para IE6 e IE7.
  • Solución de bug en el envio de mimetype al navegador.
  • Añadido método al api cliente, que permite retornar una imagen png con el código de barras y QR code del documento custodiado.
  • Se ha añadido a la demo de la plataforma la posibilidad de firmar un documento de ejemplo, sin necesidad de subir uno ya existente.
  • Mejorado el parseador de Oids, para extraer correctamente los datos del certificado.

Java: Implementación de una caché con Referencias Débiles

Posteado por Manuel Navarro Almuedo en April 10th, 2008

Últimamente me ha surgido una necesidad que hasta ahora no se me había presentado.
Os comento de qué se trata:

Estaba desarrollando una aplicación web (jsf, seam, etc.), en unos de las páginas se generaba un listado en el que se muestra datos sobre una serie de documentos.

Existe la posibilidad de descargar estos documentos, que no son más que archivos pdfs, a través de una aplicación cliente que a su vez se despliega con Java Web Start con JNLP en la misma aplicación web.
El problema es el siguiente:

El usuario X a través de la aplicación ve el listado, pero el JNLP no comparte la misma sesión que el navegador, luego no podemos acceder a dicho listado, ya que se trata de un objeto visible en el conexto Sesión.
Una primera solución consistiría en pasar los distintos identificadores de los documentos listados al JNLP a través de parámetros en la URL. Pero existe el problema de que el listado sea demasiado largo y la URL resultante sea demasiado larga, problema con caracteres no aptos para una URL, etc.  Podemos jugárnosla, optar por esta “solución” y rezar para que nunca se produzca esa situación… no mola, sigamos pensando y busquemos otra solución.
Posteriormente podemos pensar en identificar el listado y mantener los elementos relacionados en una caché. Caché que no se alojará a nivel de Sesión, sino en el conexto de la Aplicación (ServletContext), para que esté visible desde todas las sesiones (usuario web y usuario jnlp).

Pero, ¿cómo implementamos esta caché?
Usemos un simple HashMap:

El primer usuario entra, hace un listado, se introduce en la caché el listado.
El mismo usuario genera otro listado, se introduce en la caché.
Entra otro usuario, lo mismo, un nuevo elemento a la caché.
Trás introducir cinco mil elementos en la caché vemos que la aplicación ya no puede más y dice ‘¡¡ hasta aquí hemos llegado !!’.
¿Qué ha pasado? Pues que la caché ha almacenado muchísimos listados y se ha ‘comido’ muchísima memoria.

¿Cómo podríamos solucionarlo? Establezcamos un tamaño máximo de cacheo, lo que nos llevará a proponer una determinada política de reemplazo (aleatoria, LRU, LFU, FIfo). Demasiadas cosas para pensar, y teniendo en cuenta las leyes de Murphy ‘Si algo puede fallar, fallará’, así que mejor sigo investigando otra forma de implementar la caché.

Y ¿se podría implementar la caché de tal forma que el recolector de basura de Java vaya borrando sus elementos cuando se esté consumiento demasiada memoria? Esto nos lleva al concepto de “Referencia débil”.

Recordemos los tipos de referencias en Java: Fuertes, débiles, blandas y fantasma. En la práctica las débiles y las blandas son tratadas igual por la Máquina Virtual Java (no sigo explicando esto porque no es el objetivo de este post).

Cuando el recolector de basura se ejecuta y va recorriendo los distintos objetos, si estos objetos son apuntados por referencias débiles se eliminan, tal y como suena, esto no ocurre con las referencias fuertes.
¿Cómo podemos aprovechar esto en nuestra caché? Pues a través de la clase WeakHashMap (véase java.util.WeakHashMap). Esta clase implementa java.util.Map, pero las keys se almacenan como objetos con referencias débiles. Con esto se dejará la responsabilidad de vaciar la caché al recolector de basura.
Pues nada más, con esto hemos conseguido implementar una caché visible desde las distintas sesiones en una aplicación y gestionada por el Recolector de Basura.

A continuación os pongo un pequeño código de ejemplo para que podais ver la diferencia de funcionamiento entre un HashMap y un WeakHashMap.

import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;        

public class Prueba {
	public static void main(String[] args) {
		Map map = new HashMap();
		Map weakMap = new WeakHashMap();
		imprime("map", map);
		imprime("weakMap", weakMap);
		for (int i = 0; i < 50; i++) {
			System.out.println("=======================n=======================");
			System.out.println("Insertando: " + i);
			System.out.println("Insertando: " + i + "_key");
			map.put("" + i, "" + i);
			map.put("" + i + "_key", "" + i);
			weakMap.put("" + i, "" + i);
			weakMap.put("" + i + "_key", "" + i);
			imprime("map", map);
			imprime("weakMap", weakMap);
			if (map.keySet().size() != weakMap.keySet().size()) {
				System.out.println("DISTINTO TAMAÑO !!!");
			}
			System.out.println("Eliminando: " + i);
			map.remove("" + i);
			weakMap.remove("" + i);
			imprime("map", map);
			imprime("weakMap", weakMap);
		}
	}        

	private static void imprime(String texto, Map map) {
		System.out.println("n-----------" + texto + "-----------");
		System.out.println("Size: " + map.keySet().size());
		System.out.println("Map:" + map);
		System.out.println("------------------------------n");
	}
}

Por cierto, quien quiera seguir investigando las referencias débiles puede probar con la clase java.lang.ref.WeakReference.

Saludos.

Spring vs Seam (La guerra ha empezado)

Posteado por Félix García Borrego en April 10th, 2008

Como primer contrincante tenemos Spring, un framework muy extendido, al que le empezaban a pesar las arrugas, y que tras su última actualización ha vuelto a rejuvenecer.

Como segundo contrincante tenemos Seam, un framework joven, y con una nueva filosofía.

He de reconocer que cada vez me gusta mas Spring, cada vez se parece más a Jboss Seam :p. Os dejo algunos ejemplos en los que el nuevo Spring ha seguido el camino marcado por Seam, abandonando los “desagradables” xmls de mapeo declarativo, para ofrecer la misma funcionalidad con anotaciones.

Gestión de transacciones con Spring:

@Transactional(readOnly = false)
void postComment(long articleId, Comment comment);

Gestión de transacciones con Seam:

@Transactional
void postComment(long articleId, Comment comment);

Publicación de Manager JSF Beans con Spring 2.5:

@Controller(”PersonaController”)
@Scope(”session”)
public class PersonaController{
..
}

Publicación de Manager JSF Beans con Seam:

@Name("personaController")
@Scope(SESSION)
public class PersonaController{
..
}

La verdad es que revisando una a una las nuevas anotaciones y funcionalidades que proporciona Spring, solo me queda alegrarme por el parecido. Estoy seguro que con esta competencia ganamos todos, por ahora estoy del lado de Seam ya que su enfoque resulta menos forzado y mucho mas alineado con los futuros Web Beans, pero quien sabe lo que nos depara el futuro.

Los que quieran profundizar en las diferencias,  pueden ver Framework Deachmatch: Spring vs Seam[pps]

También se han publicado una serie de artículos muy interesantes sobre como integrar Spring con Seam.

Framework Seam: autorización en aplicaciones

Posteado por Manuel Navarro Almuedo en March 4th, 2008

Como todos ya sabemos uno de los puntos importantes de una aplicación web es el control de la seguridad en cuanto a la autenticación y la autorización de usuarios.

Básicamente a la Autenticación le corresponde la tarea de ver quién es el usuario y a la Autorización le corresponde permitir o no el acceso a las distintas zonas de una aplicación web a partir, por ejemplo, de su perfil en la aplicación.

En este post me centraré en la Autorización, ya que Jboss Seam tiene mucho que decir al respecto, y os muestro una posible implementación para controlar el acceso de un usuario a una “zona” determinada de una aplicación.

Supongamos una aplicación con dos zonas, una zona de administración y una zona de acceso a usuarios. Para la primera zona (http://<aplicacion>/admin) se necesita que el usuario posea el rol “admin”, mientras que para la segunda(http://<aplicacion>/usuario) el rol “usuario”, nos centraremos en la primera, la segunda os la dejo como ejercicio…
También supongamos que tenemos un objeto “authenticator” que implementa los distintos métodos que requiere Seam respectos a la autenticación.
Normalmente, cuando un usuario entra en la aplicación sin haberse logado Seam lanza la excepción “NotLoggedInException” y posteriormente se redirige al usuario a la correspondiente pantalla para logarse. Este comportamiento se controla mediante el archivo “pages.xml”:
<exception class=”org.jboss.seam.security.NotLoggedInException“>
<redirect view-id=”/index.xhtml“>
<message>Usted debe estar logado para acceder a esta página.</message>
</redirect>
</exception>

Tras introducir los datos para el login (usuario y contraseña, certificado digital, etc.), el método “returnTo” del “autenticator” nos redirige a la zona adecuada, según observemos el rol que tiene asignado el usuario, esto lo podemos indicar en el fichero “components.xml”:
<event type=”org.jboss.seam.postAuthenticate“>
<action execute=”#{authenticator.returnTo}“/>
</event>

Una primera propuesta (adelanto que no es la definitiva), para controlar el acceso a la zona “admin” podríamos definir en el pages.xml lo siguiente:

<page  view-id=”/admin/*” login-required=”true”>
<restrict>#{s:hasRole(’admin’)}</restrict>
</page>

<exception class=”org.jboss.seam.security.AuthorizationException“>
<end-conversation/>
<redirect view-id=”/index.xhtml“>
<message>Usted no posee los privilegios suficientes para acceder a esta zona.</message>
</redirect>
</exception>

Que en Castellano significa: para las peticiones a “/admin/*” comprueba que el usuario tiene el rol “admin”. Cuando no lo tenga se lanzará la correpondiente excepción “AuthorizationException” y se le redirigirá a “/index.xhtml” mostrándose el mensaje “Usted no posee los privilegios suficientes para acceder a esta zona.”

Quizás si no vamos más allá podamos pensar que tenemos todo controlado, pero ahora imaginemos la siguiente situación:

1) Un usuario entra en la aplicación, se va a la página de Login (por el NotLoggedInException capturado) y se loga correctamente, sin rol “admin” por lo que no debería tener acceso a /admin, de hecho el “return True” le redirige a la zona pública.
2) El usuario que se cree un piratilla escribe a fuego en la barra de direcciones del navegador “/admin” y le da al botón de Enter…

¿Qué pasará?
Lo esperado es que si el usuario pide “manualmente” en /admin tras logarse y obtener únicamente el rol “usuario”, la aplicación genera un AuthorizationException y se le redirigirá a /index.xhtml (pantalla inicial de bienvenida)…
Hazlo y comprobarás que no… el usuario tiene acceso a la zona de administración.

¿Y porqué? Pues una de las causas que he leído en el foro de jboss es que “esa excepción no se trata en la fase de render del JSF” y entonces no tiene el comportamiento que se indica en el pages.xml. Quizás no haya que buscar más porqués y proponer otra solución.
Una segunda propuesta, bastante atractiva aunque después propondré otra ligeramente más refinada, trata de que la aplicación capture correctamente la excepción AuthorizationException, nos redirija al index.xhtml y no suponga tener que redefinir arquitectura de ningún tipo… allá va:
Deberemos crear un nuevo “Controller” como este, especialmente dedicado a controlar el acceso a la zona de administración, quizás se podría usar cualquier controller ya existente, pero así queda más limpito nuestro código (vease “asignación de responsabilidades”):
@Name(”authorizationAdminController”)
@Scope(CONVERSATION)
@Restrict(”#{s:hasRole(’admin’)}”)
public class AuthorizationAdminController extends ControllerJsfApplication {
public void forceCheckAdminAuthorization(){}
}

Vemos que queda un controller práctiamente vacío.
Debido a @Restrict sólo podrán “invocar” a este controller los Identities(usuarios logados) con rol “admin”.

Ahora modificamos nuestro pages.xml de la siguiente forma:
Donde antes teníamos:
<page  view-id=”/admin/*” login-required=”true”>
<restrict>#{s:hasRole(’admin’)}</restrict>
</page>

Ahora tenemos:
<page  view-id=”/admin/*” login-required=”true” action=”#authorizationAdminController.forceCheckAdminAuthorization}“>
</page>
Con lo que al hacer una petición a “/admin” se ejecutará el action ( authorizationAdminController.forceCheckAdminAuthorization ), el cual no podrá estar accesible si no se posee el rol “admin”, debido a la anotación @Restrict del controller. Si el identity no posee este rol se lanza AuthorizationException, igual que pasaba antes sin usar el controller, sólo que ahora esta excepción si se captura correctamente y se realiza la redirección indicada en el pages.xml.
También deberemos mantener:
<exception class=”org.jboss.seam.security.AuthorizationException”>
<end-conversation/>
<redirect view-id=”/index.xhtml”>
<message>Usted no posee los privilegios suficientes para acceder a esta zona.</message>
</redirect>
</exception>
Con esta modificación conseguimos proteger correctamente la zona “/admin”, un usuario que intente logarse y posteriormente entrar en “/admin”, esta vez se le mostrará el index.xhtml con el mensaje: “Usted no posee los privilegios suficientes para acceder a esta zona.”
Una tercera solución es simplemente un refinamiento de la segunda, y llegamos a ella a través de la pregunta:
Si tenemos 50 zonas de protegidas, ¿tendremos que implementar 50 Controller semejantes a “AuthorizationAdminController” pero con un @Restrict distinto?
Pues no, la solución está en no anotar el Controller con @Restrict, sino anotar el propio método, así podríamos tener un único controller y N métodos para comprobar distintas autorizaciones:

@Name(”authorizationAdminController”)
@Scope(CONVERSATION)
public class AuthorizationAdminController extends ControllerJsfApplication {

@Restrict(”#{s:hasRole(’admin’)}”)
public void forceCheckAdminAuthorization(){}

@Restrict(”#{s:hasRole(’usuario’)}”)
public void forceCheckUsuarioAuthorization(){}

………

@Restrict(”#{s:hasRole(’XXXX’)}”)
public void forceCheckXXXXXXXAuthorization(){}

}

Indicando en el pages.xml el método “forceCheck X Authorization” que corresponde a cada zona las protegeremos convenientemente.

Pues con esto ha acabado lo que ha intentado ser una explicación.

Nunca olvidaré esta “primera vez” en que escribí en xnoccio, espero que hallais disfrutado tanto como yo.

Que la suerte os acompañe !!

Seam en aplicaciones Standalone

Posteado por Félix García Borrego en February 20th, 2008

Jboss Seam es un magnífico framework para el desarrollo de aplicaciones Web, pero plantea algunos problemas, cuando deseamos reutilizar nuestro código Seam  desde una aplicación que no se esta ejecutando dentro de un servidor de aplicaciones o desde un Thread independiente. Esto es debido a que sin la envoltura del servidor de aplicaciones, ninguno de los contextos Seam estarán disponibles.

El error típico con el que nos vamos a encontrar es:


java.lang.IllegalStateException: No application context active
at org.jboss.seam.Component.forName(Component.java:1807)

Código para inicializar Seam antes de utilizarlo:


     /**
     * Inicializa el contexto Seam.
     * Necesario para ejecutar código cuando el contexto Seam no esta inicializado y necesitamos acceder a elementos del contexto.
     * Con esto evitamos la excepción "No application context active"
     * @author Félix García Borrego
     */
    public static void initContextApplication(){
        if(!Contexts.isApplicationContextActive()){
        // Si el contexto no esta inicializado lo creamos
       if(!Lifecycle.isApplicationInitialized()){
            // La aplicación no esta activa, la activamos
            MockServletContext servletcontextMock = new MockServletContext();
            ServletLifecycle.beginApplication(servletcontextMock);
            new Initialization(servletcontextMock).create().init();
     }
     // Inicializamos el contexto
     ServletLifecycle.beginInitialization();
 }

Sun’s RI for JSF vs MyFaces

Posteado por Félix García Borrego en January 21st, 2008

Época de despedidas, hoy le toca el turno a MyFaces

Después de más de dos años utilizando la implementación Apache Myfaces JSF, ha llegado el momento de las despedidas, en adelante todos nuestros proyectos se pasan a la implementación JSF 1.2 de Sun. No existe un motivo principal, pero si muchos pequeños problemas que finalmente nos han hecho decidirnos por la migración. Sin intención de entrar en detalle, estas son las motivaciones principales:

- En el momento de tomar la decisión, la implementación de Sun de la especificación 1.2 era mucho mas madura que la de Myfaces. En las pruebas realizadas pudimos comprobar que el numero de bugs es mucho mayor en la implementación Myfaces. En general Sun’s RI es una implementación mucho mas pulida.

- El número de incompatibilidades que hemos sufrido al migrar de la especificación 1.1 a 1.2 ha sido mucho menor con la implementación de Sun.

- Es posible seguir utilizando las librerías Tomahawk  con la implementación de Sun.

- La implementación de Sun parece ofrecer mejor rendimiento que la implementación de Myfaces.

- La integración con Seam es mucho mas sencilla utilizando la implementación de Sun.

- Gracias a la filosofía una especificación, múltiples implementaciones; el cambio era posible.