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

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.

Te Puede Interesar

Tags: , , , , ,

blog comments powered by Disqus

© 2009 JotaDeveloper. Nuestros contenidos están bajo licencia Creative Commons mientras no se indique lo contrario,
y pueden reproducirse libremente sin más que mencionar la fuente ("JotaDeveloper") y la URL concreta del artículo original. .

This blog is powered by Wordpress and JotaDeveloperTheme.