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 :
- Configuración Spring Security 2.0 con JDBC
- Configuración Spring Security 2.04 para LDAP
- La Seguridad Perfecta con Spring y el dropDownMenu de RichFaces
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.
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.




Últimos comentarios