RichFaces El Componente Tree, leyendo un directorio

1 Comment

tree

RichFaces, nos ofrece una forma facil de generar Arboles (Tree) con solo agregarle un Collection, List o un Array, el ejemplo siguiente, sacado del live demo de RichFaces es un ejemplo sencillo de como leer un directorio y convertirlo en un arbol. El componente rich:recursiveTreeNodesAdaptor que se agrega internamente, se encarga de identificar de los elementos de la raíz tienen a su vez mas elementos, y asi mostrarlos como carpetas o archivos.

En el siguiente ejemplo, la clase TreeNodeTest inicia una busqueda en el directorio indicado en SRC_PATH y llama a la función getSourceRoots().getNodes() que a su vez recupera el listado de carpetas y archivos, como puedes ver en la imagen, cuando haces click en las carpetas (que a su vez son objetos arrays con elementos), el inicia otra busqueda, por eso la propiedad nodes=”#{item.nodes}” que busca si Object[] nodes tiene algún elemento. Este proceso se repite hasta que el último elemento del arbol no encuentre mas elementos.

public class FileSystemNode {
	private String path;
	private static FileSystemNode[] CHILDREN_ABSENT = new FileSystemNode[0];
	private FileSystemNode[] children;
	private String shortPath;
 
	public FileSystemNode(String path) {
		this.path = path;
		int idx = path.lastIndexOf('/');
		if (idx != -1) {
			shortPath = path.substring(idx + 1);
		} else {
			shortPath = path;
		}
	}
 
	public synchronized FileSystemNode[] getNodes() {
		if (children == null) {
			FacesContext facesContext = FacesContext.getCurrentInstance();
			ExternalContext externalContext = facesContext.getExternalContext();
			Set resourcePaths = externalContext.getResourcePaths(this.path);
			if (resourcePaths != null) {
				Object[] nodes = (Object[]) resourcePaths.toArray();
				children = new FileSystemNode[nodes.length];
				for (int i = 0; i < nodes.length; i++) {
					String nodePath = nodes[i].toString();
					if (nodePath.endsWith("/")) {
						nodePath = nodePath.substring(0, nodePath.length() - 1);
					}
					children[i] = new FileSystemNode(nodePath);
				}
			} else {
				children = CHILDREN_ABSENT;
			}
		}
		return children;
	}
 
	public String toString() {
		return shortPath;
	}
}
public class TreeNodeTest {
 
	private static String SRC_PATH = "/WEB-INF/classes";
	private FileSystemNode[] srcRoots;
	private Log log = LogFactory.getLog(this.getClass());
 
	public synchronized FileSystemNode[] getSourceRoots() {
		if (srcRoots == null) {
			srcRoots = new FileSystemNode(SRC_PATH).getNodes();
		}
 
		return srcRoots;
	}
}
	<rich:tree style="width:300px" switchType="ajax">
	<rich:recursiveTreeNodesAdaptor	roots="#{treeNodeLocationBean.sourceRoots}" var="item"
	nodes="#{item.nodes}" />
	</rich:tree>

Google Maps para JSF + Facelets

2 Comments

gmaps4jsf-logo

GMAP4JSF es una libreria genial para integrar Google Maps en tu Sitio Web, yo hace un par de años tuve experiencia con el API de Google Maps y habia que tener conocimientos de Javascript para poder elaborar algunas maravillas, pero con este framework no hace falta y es muy facil de usar, empecemos con la instalación.

Primero Descárgate el JAR gmaps4jsf-core-1.1.1.jar, e incorporalo a tus librerias.

(more…)

Spring Security 2, la configuración a la medida con DAO Hibernate III

No Comments

El dia de hoy vamos a continuar con los Filtros, es la parte central de la seguridad de Spring, y por eso la hace tan flexible, porque esta completamente separada del modelo de Negocio, eso es lo que lo hace tan genial, pues si el dia de mañana se te ocurre cambiar toda la seguridad, tu sistema no sufrirá grandes cambios.

Los filtros se encargan de la seguridad de la aplicación. Existen tres filtros fundamentales se encadenan juntos mediante un objeto llamado “filterChainProxy”, que crea e inicializa los tres filtros; como se ve en el siguiente diagrama.

filtrosacegi

  1. El filtro AuthenticationProcessingFilter maneja la petición o requerimiento (request) que chequea la autenticación -Authentication Request Check- (“el login de la aplicación”). Para ello usa el AuthenticationManager que vimos en el articulo anterior.
  2. El filtro HttpSessionContextIntegrationFilter mantiene el objeto Authentication entre varios requests y se lo pasa al AuthenticationManager y al AccessDecisionManager cuando sea necesario.
  3. El filtro ExceptonTranslationFilter verifica la existencia de autenticación , maneja las excepciones de seguridad y ejecuta la acción apropiada. El ExceptonTranslationFilter depende del filtro siguiente, FilterSecurityInterceptor.
  4. FilterSecurityInterceptor controla el acceso restricto a recursos determinados , y el chequeo de autorización.  Conoce qué recursos son seguros y qué roles tienen acceso a ellos.  FilterSecurityInterceptor usa el AuthenticationManager y el AccessDecisionManager para hacer su trabajo.

Cuando inicias, todo esto es una maraña de filtros sin sentido, pero vamos a profundizar un poco para que te quede más claro la funcion y configuración de cada uno de ellos.

AuthenticationProcessingFilter

El primer filtro donde pasa el RequestHTTP. Este filtro se especializa en manejar el request de autentificación, valida el usuario y la contraseña, más alla de esto solo debes conocer otros parametros imporantes.

  • authenticationFailureUrl: En el caso de fallo, algún lugar debe de ir cuando no se logea el usuario.
  • defaultTargetUrl: Es el URL por defecto, generalmente es la raiz.
  • filterProcessesUrl: Es a quien le encarga la responsbilidad de verificar si el usuario se logea o no..
<bean id="authenticationProcessingFilter"
		class="org.springframework.security.ui.webapp.AuthenticationProcessingFilter">
		<property name="authenticationManager">
			<ref bean="authenticationManager" />
		</property>
		<property name="authenticationFailureUrl">
			<value>/login.me</value>
		</property>
		<property name="defaultTargetUrl">
			<value>/</value>
		</property>
		<property name="filterProcessesUrl">
			<value>/j_spring_security_check</value>
		</property>
	</bean>

HttpSessionContextIntegrationFilter

El HttpSessionContextIntegrationFilter es fácil de configurar. Su única función, es propagar por el Contexto de Seguridad la autenticación a través de todas las solicitudes. No necesita propiedades ni nada en especial.

<bean id="httpSessionContextIntegrationFilter"
		class="org.springframework.security.context.HttpSessionContextIntegrationFilter" />

ExceptionTranslationFilter

El filtro ExceptionTranslationFilter intercepta cualquier error de autenticación o autorización, por ejemplo UsernameNotFoundException o DataAccessException.

Si la excepción fue causada por una excepción de autorización lanzada por el filtro FilterSecurityInterceptor (puede ser porque no tiene permisos para acceder a un Recurso Web, una imagen o un URL), el filtro lanzará un HTTP 403 al navegador, el cual mostrará una página de acceso no autorizado.

<bean id="formExceptionTranslationFilter"
		class="org.springframework.security.ui.ExceptionTranslationFilter">
		<property name="authenticationEntryPoint">
			<ref local="formEntryPoint" />
		</property>
	</bean>
 
<bean id="formEntryPoint"
		class="org.springframework.security.ui.webapp.AuthenticationProcessingFilterEntryPoint">
		<property name="loginFormUrl" value="/login.me" />
	</bean>

FilterSecurityInterceptor

El FilterSecurityInterceptor, es donde protegeremos todos nuestros recursos, donde decidimos que ROL entra a ciertos recursos, cuales pueden ser accedido por usuarios anónimos, todo esto se configura en el objectDefinitionSource. Necesitamos 2 referencias para configurar este Filtro, el authenticationManager y el bean accessDecisionManager que miraremos en el siguiente artículo.

<bean id="filterInvocationInterceptor"
		class="org.springframework.security.intercept.web.FilterSecurityInterceptor">
		<property name="authenticationManager" ref="authenticationManager" />
		<property name="accessDecisionManager" ref="voteAccessDecisionManager" />
		<property name="objectDefinitionSource">
			<value>
				CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
				PATTERN_TYPE_APACHE_ANT
				/=ENCUESTAME_ANONYMOUS
				/pages/**=ENCUESTAME_USER
				/pages/admon/**=ENCUESTAME_ADMIN
				/user/**=ENCUESTAME_ANONYMOUS,ENCUESTAME_USER,ENCUESTAME_ADMIN
         </value>
		</property>
	</bean>

FilterChainProxy

El filtro inicializador, su función principal es indicar o personalizar, que recursos ejecutaran los filtros deseados en filterInvocationDefinitionSource, por ejemplo, si tenemos un sevlet /uploadFile y solo nos interesa aplicar algunos filtros

<bean id="springSecurityFilterChain" class="org.springframework.security.util.FilterChainProxy">
      <property name="filterInvocationDefinitionSource">
         <value>
		   CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
		    PATTERN_TYPE_APACHE_ANT
               /**=httpSessionContextIntegrationFilter,logoutFilter,basicProcessingFilter,authenticationProcessingFilter....
              /uploadFile= basicProcessingFilter,OtroFiltroPersonalizado
         </value>
      </property>
    </bean>

En el siguiente artículo, veremos una extensión de los diferentes filtros opcionales que podemos integrar en nuestra seguridad, ¿preguntas?

RichFaces 3.3.1 viene con Nuevos Componentes

No Comments

El equipo RichFaces ha liberado RichFaces 3.3.1 GA. Este lanzamiento incluye algunos nuevos compoentes y una aplicación demo nuevo ademáas de la constante correción de errores.

Nuevos Componentes

rich:colorPicker -  ahora podrás elegir visualmente en una paleta de colores o con el color en hexadecimal el color deseado. Ejemplo demo.

rich:page – puedes construir una estructura de página, con su header, footer y toolBar, y cambiarlos dinamicamente.
rich:layout, rich:layoutPanel - Estos componentes sirven para crear la estructura del componente anterior.

Revisa el demo de estos últimos tres componentes.

Nueva Aplicación Demo

Puedes ver el nuevo Photo Album demo application construido con RichFaces.

Como twittear desde Java

1 Comment

twitter-logo

Ya que me metí a la moda del twitter, me puse indagar y existen unas cuantas librerias para twittear desde Java, esta es la que más me gusto, Twitter4J,tal vez una de las más faciles de usar, veamos unos ejemplos.

Para obtener una lista de tus últimos mensajes

 public static void main(String[] args) {
		    Twitter myTwitter = new Twitter(tUser, tPass);
		    try{
		        List utl = myTwitter.getUserTimeline();
		        for(Status a : utl){
		          // Obtenemos el avatar del usuario loggueado
		          System.out.println("Imagen: " +
		                a.getUser().getProfileImageURL().toString());
		          // Obtenemos la fecha de creacion del mensaje
		          System.out.println("Fecha: " + a.getCreatedAt());
		          //Obtenemos el mensaje
		          System.out.println("Mensajes: " + a.getText());
		        }
		    }catch(Exception e){
		     System.out.print(e.getMessage());
		    }
		  }

Si queremos conocer los últimos mensajes de @gandulo, pues este seria el código

		Twitter myTwitter = new Twitter(tUser, tPass);
		try {
			List utl = myTwitter.getUserTimeline("gandulo");
			for (Status a : utl) {
				// Obtenemos el avatar del usuario loggueado
				System.out.println("Imagen: "
						+ a.getUser().getProfileImageURL().toString());
				// Obtenemos la fecha de creacion del mensaje
				System.out.println("Fecha: " + a.getCreatedAt());
				// Obtenemos el mensaje
				System.out.println("Mensajes: " + a.getText());
			}
		} catch (TwitterException e1) {
			System.out.print(e1.getMessage());
		}

Para postear un mensaje

          Twitter myTwitter = new Twitter(tUser, tPass);
		try {
			Status status = myTwitter.update("mi mensaje");
		} catch (TwitterException e) {
			e.printStackTrace();
		}

Para enviar un mensaje privado a alguien

      Twitter myTwitter = new Twitter(tUser, tPass);
      try {
      myTwitter.sendDirectMessage("gandulo", "Saludando");
	} catch (TwitterException e1) {
	System.out.print(e1.getMessage());
	}

Para agregar o eliminar a alguien

//Agregar
Twitter myTwitter = new Twitter(tUser, tPass);
		try {
			myTwitter.create("ajulloa");
		} catch (TwitterException e) {
			e.printStackTrace();
		}
//Eliminar
 
Twitter myTwitter = new Twitter(tUser, tPass);
		try {
			myTwitter.destroy("ajulloa");
		} catch (TwitterException e) {
			e.printStackTrace();
		}

Spring Security 2, la configuración a la medida con DAO Hibernate II

1 Comment

Siguiendo con el articulo anterior, voy a explicar los diferentes Filtros de Seguridad y las Configuraciones Personales que podemos aplicar en nuestra Seguridad. El siguiente gráfico explica el ciclo de vida de la autentificación en Spring.

En el post anterior, vimos el Bean del Formulario de logeo, donde se creo el objeto Authentication que se pasa al AuthenticationManager.

UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(userName, password);
.......
Authentication auth = getAuthenticationManager().authenticate(authReq);

spring_exception_filter

AuthenticationManager

El bean AuthenticationManager es del tipo ProviderManager, lo que significa que actúa de proxy con AuthenticationProvider. En Spring, el AuthenticationProvider es el encargado de validar la combinación nombre de usuario/contraseña por medio del objeto Authentication  y retornar los roles asociados a dicho usuario. Esta clase tan sólo delega la autenticación en una lista de proveedores configurable, cada uno de los cuales implementa el interfaz AuthenticationProvider. Hay muchos tipos de AuthenticationProvider( JDBC, Hibernate,  LDAP, RememberMe, OpenID). Usted puede indicar cuales quiere usar son los proveedores de autentificación que desee usar, en nuestro caso, usaremos un DAO Hibernate personalizado.

<bean id="authenticationManager" class="paquete.MiAuthenticationManager">
	<property name="providerString" value="userDaoProvider" />
</bean>
public class MiAuthenticationManager extends ProviderManager {
protected String providerString;
public void setProviderString(String providerString) {
		this.providerString = providerString;
	}
 /**
  * Agrega al Manejador de Proveedores un listado
  */
public void afterPropertiesSet() throws Exception {
		if (providerString != null) {
			List<authenticationprovider> providers = new LinkedList();
			String[] names = providerString.split(",");
			for (String providerUnit : names) {
				AuthenticationProvider provider = (AuthenticationProvider) applicationContext
						.getBean(providerUnit.trim());
				if (provider == null) {
 
					throw new EnMeExpcetion("AuthenticationProvider "
							+ providerUnit + " don't exist");
				}
				providers.add(provider);
			}
			setProviders(providers);
		}
		super.afterPropertiesSet();
	}
}
 
</authenticationprovider>

DaoAuthenticationProvider

DaoAuthenticationProvider, es el comúnmente usado puesto que es el que permite acceder a la información almacenada en una base de datos. El proveedor DaoAuthenticationProvider merece una mención especial. Esta implementación delega a su vez en un objeto de tipo UserDetailsService, un interfaz que define un objeto de acceso a datos con un único método loadUserByUsername que permite obtener la información de un usuario a partir de su nombre de usuario.

<bean id="userDaoProvider"
		class="org.springframework.security.providers.dao.DaoAuthenticationProvider">
		<property name="userDetailsService" ref="dbUserService" />
	</bean>

Si deseas agregarle encriptación a la contraseña del usuario, agregale una propiedad más al userDaoProvider, este artículo que escribi tiempo atrás te ayudará a poner una mejor seguridad que el tipico MD5.

UserDetailsService, un Dao Personalizado

Si no queremos que Spring acceda a la bases de datos directamente podemos configurar un Dao personalizado por medio de una Implementación UserDetailsService, , un interfaz que define un objeto de acceso a datos con un único método loadUserByUsername que permite obtener la información de un usuario a partir de su nombre de usuario.

 
<bean id="dbUserService" class="paquete.MiUserServiceImp">
		<property name="userDao" ref="userDao" />
	</bean>


public class MiUserServiceImp implements UserDetailsService {
         ......
        public UserDetails loadUserByUsername(String username)
			throws UsernameNotFoundException, DataAccessException {
		SecUsers user = userDao.getUser(username);
		if (user == null) {
			log.info("no encontrado...");
			throw new UsernameNotFoundException("username");
		}
		return convertToUserDetails(user);
	}
 
         ......
 
    protected UserDetails convertToUserDetails(SecUsers user){
         //lista de permisos,
         List<string> listPermissions = new ArrayList</string><string>();
        ...........
        GrantedAuthority[] authorities = new GrantedAuthority[listPermissions
				.size()];
		int i = 0;
		for (String permission : listPermissions) {
			authorities[i++] = new GrantedAuthorityImpl(permission.trim());
		}
 
		User userDetails = new User(user.getUsername(), user.getPassword(),
				user.isStatus() == null ? false : user.isStatus(), true,
				true,
				true,
				authorities);
		log.info("userDetails "+userDetails);
		return userDetails;
    }
}
</string>

Vamos a dejar la explicación de los Filtros, para una tercera parte, ya se hizo largo :) .

Spring Security 2, la configuración a la medida con DAO Hibernate I

No Comments

Uno de los aspectos que toda aplicación debe considerar es la seguridad, entendiendo como tal la necesidad de saber que el usuario es quien dice ser (autenticación), y permitirle acceso sólo a aquellos recursos necesarios (autorización). En un princio el framework  se llamaba Acegi Security e inicio en el 2003, 5 años después en Abril del 2008 se incorporó al portafolio de Spring Framework como un súbmodulo. Spring trae por defecto ciertas caracteristicas que a la hora de querer integrarlas en nuestros sistemas avanzados no encajan a la perfección y por lo general se necesitan modificaciones a las clases principales.

Anteriormente hemos visto configuraciones mucho más sencillas :

Creo que una de las configuraciones más complejas es fusionando con el framework Hibernate y esto nos permite no anclarnos a las tablas que ya Spring Security trae por defecto, asi poder personalizar nuestra seguridad de una mejor manera.

uml

En nuestro caso vamos a trabajar con Spring Framework, y lo ideal es separar nuestra aplicación en 3 capas:

  • Capa de Presentación: En esta capa vamos a programar el formulario, el típico formulario con el nombre de usuario y la contraseña, podemos integrar OPEN ID, e incluso la funcionalidad de Recordar la Sessión por medio de un Cookie.
  • Filtros de Seguridad: Aqui aplicaremos toda la configuración de Spring Security, aplicaremos todos los filtros y las clases que vamos a modificar algunas clases de Spring que se comuniquen con nuestros servicios en la capa de negocio.
  • Servicios en la Capa de Negocio: En esta capa colocaremos nuestros Beans de Spring que a su vez acceden a otra capa en la cual no vamos a entrar en detalle, la de acceso a datos.

Iniciemos con la capa de presentación y el formulario para logearse, en su forma más sencilla, aqui se pueden agregar validadores y mensajes de error, etc.

	<h :inputText id="j_username"  value="#{loginForm.userName}" size="40" required="true"/>
	<h :inputSecret id="j_password" value="#{loginForm.userPassword}" size="40" required="true"/>
	<h :commandButton action="#{loginForm.login}"  value="Iniciar Sesión"/>

Ahora necesitamos nuestro Bean LoginForm, este puedes colocarlo como un ManageBean o un Bean de Spring, como mas te parezca, en mi caso use Spring.

public class LoginForm{
 
        //Bean Personalizado del Manejador de Autentificación
	private AuthenticationManager authenticationManager;
	private String userName;
	private String userPassword;
	private Application app;
 
 
	public String getUserName() {
		return userName;
	}
 
	public void setUserName(String userName) {
		this.userName = userName;
	}
 
	public String getUserPassword() {
		return userPassword;
	}
 
	public void setUserPassword(String userPassword) {
		this.userPassword = userPassword;
	}
 
	public AuthenticationManager getAuthenticationManager() {
		return authenticationManager;
	}
 
	public void setAuthenticationManager(
			AuthenticationManager authenticationManager) {
		this.authenticationManager = authenticationManager;
	}
 
	/**
	 *
 
	/**
	 * Ejecuta un envio a un url definido por la navegación JSF
	 * @param viewId
	 */
	protected void forward(String viewId) {
    	ViewHandler viewHandler = getApplication().getViewHandler();
	    FacesContext facesCtx = getFacesContext();
	    UIViewRoot view = viewHandler.createView(facesCtx, viewId);
	    facesCtx.setViewRoot(view);
	    facesCtx.renderResponse();
	}
 
	/**
	 * Obtiene el contexto de la Aplicación
	 * @return
	 */
	protected Application getApplication() {
		if (app == null) {
			ApplicationFactory appFactory = (ApplicationFactory) FactoryFinder.getFactory(FactoryFinder.APPLICATION_FACTORY);
	        app = appFactory.getApplication();
		}
		return app;
	}
 
	/**
	 * Obtiene el Contexto de JSF
	 * @return
	 */
	protected FacesContext getFacesContext() {
		return FacesContext.getCurrentInstance();
	}
 
	/**
	 * Obtiene la Petición del HttpServletRequest
	 * @return
	 */
	protected HttpServletRequest getRequest() {
		ExternalContext context =
			FacesContext.getCurrentInstance().getExternalContext();
	    HttpServletRequest request =
	    	(HttpServletRequest) context.getRequest();
	    return request;
	}
 
	/**
	 * Obtiene la Respuesta del HttpServletResponse
	 * @return
	 */
	protected HttpServletResponse getResponse() {
		ExternalContext context =
			FacesContext.getCurrentInstance().getExternalContext();
		HttpServletResponse response =
	    	(HttpServletResponse) context.getResponse();
 
	    return response;
	}
 
 
	public String login() {
		HttpServletRequest request = getRequest();
	    try {
 
 
               /**
                 * Obtenemos del Formulario los Datos, por mayor seguridad podriamos agregar filtros contra XSS e Inyección HQL
                 * Creamos un token para Spring
                 */
	    	String userName = getUserName();
	    	String password = getUserPassword();
 
	    	/**
                 * Creamos un token para Spring
                 */
	    	UsernamePasswordAuthenticationToken authReq = new UsernamePasswordAuthenticationToken(userName, password);
 
               /**
                 * Le agregamos al token el request de HttpServletRequest
                 */
	    	authReq.setDetails(new WebAuthenticationDetails(request));
	    	HttpSession session = request.getSession();
 
 
               /**
                 * Asignamos la sesión el atributo UserName
                 * Obtenemos el manager auth y le asignamos el token
                 */
	    	session.setAttribute(AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY, userName);
	    	Authentication auth = getAuthenticationManager().authenticate(authReq);
 
                  /**
                 * Obtenemos el Contexto de Spring Security
                 * Le asignamos el Autentication Manager al Contexto de Seguridad
                 */
 
	    	SecurityContext secCtx = SecurityContextHolder.getContext();
	    	secCtx.setAuthentication(auth);
	    	session.setAttribute(HttpSessionContextIntegrationFilter.SPRING_SECURITY_CONTEXT_KEY, secCtx);
 
	    	String urlKey = AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY;
	    	SavedRequest savedRequest = (SavedRequest)session.getAttribute(urlKey);
	    	session.removeAttribute(urlKey);
 
	    	String target = "/index.jsf";
	    	/**
                  * Si perdiste la sesión en una página en particular, este parametro te ayudara a regresar a donde perdiste la sesión
                 */
	    	if (savedRequest != null) {
		    	String targetUrl = null;
	    		targetUrl = savedRequest.getFullRequestUrl();
	    		FacesContext.getCurrentInstance().getExternalContext().redirect(targetUrl);
	    		return null;
	    	} else {
	    		.................
	    	}
	    	/**
                 * Si no existiera un SavedRequest, entonces te enviaria a la pagina de inicio
                  */
	    	forward(target);
 
	    } catch (BadCredentialsException e) {
	    	...............
	    	return null;
	    } catch (AuthenticationException e) {
	    	............
	    	return null;
	    } catch (IOException ioException) {
	       ..............
	    }
 
	return "index";
	}
    }
}

Y como lo vamos a integrar con Spring, la declaración del Bean en el contexto

   <bean id="loginForm" class="org.xxx.LoginForm" scope="request">
		<property name="authenticationManager" ref="authenticationManager" />
	</bean>

En la parte II miraremos los Filtros de Seguridad.