Bienvenido a re-orientation! Esperamos que encuentres lo que buscas

Implementando nuestro proveedor de autenticación personalizado. La clase CustomJdbcDaoImpl


Parte del manual paso a paso para desarrollar una aplicación web con Spring Framework + Spring Security contra una base de datos MySQL.

Una vez que ya tenemos nuestro SecurityUser, toca el turno a la clase a medida CustomJdbcDaoImpl que hemos declaramos en el security-context.xml. Vamos a centrarnos en las modificaciones a realizar en el proceso de recuperación de la información del usuario, y una vez más nos apoyaremos en las clases de Spring y las extendemos para incorporar información extra.

La clase CustomJdbcDaoImpl

La nueva clase de acceso a datos CustomJdbcDaoImpl extenderá las funcionalidades de la clase de Spring JdbcDaoImpl incluyendo nuestra consulta personalizada (DEF_USERS_BY_USERNAME_QUERY) para recuperar la información del usuario buscando por el campo “username” del modelo de datos.

Esta select la ejecutaremos en el método loadUserByUsername, según se declara en la interfaz que aquí implementamos (UserDetailsService). En nuestra implementación sin embargo vamos a devolver un SecurityUser, esto es posible debido a que esta clase extiende de User, que a su vez implementa UserDetails.

Otro método que necesitamos crear en nuestra clase es createUserDetails. que va a sobre-escribir el método con el mismo nombre invocado desde la clase JdbcDaoImpl para incluir la información adicional.

Nuestra clase CustomJdbcDaoImpl queda así:

package com.reor.app01.security;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl;


public class CustomJdbcDaoImpl extends JdbcDaoImpl implements UserDetailsService {
	
	public static final String DEF_USERS_BY_USERNAME_QUERY = "select " +
            "user_id, username, password, enabled, nombre, " +
            "apellidos, fecha_nacimiento, sexo, fecha_alta, " +
            "fecha_modificacion, huso_horario, correo_electronico_ppal, tracking " +
            "from USERS " +
            "where username  = ? ";
	
	public CustomJdbcDaoImpl() {}

    protected List loadUsersByUsername(String username) {
        
    	return getJdbcTemplate().query(DEF_USERS_BY_USERNAME_QUERY, new String[] {username}, new RowMapper() {
            public UserDetails mapRow(ResultSet rs, int rowNum) throws SQLException {
                
            	Long userId = rs.getLong(1);
            	String username = rs.getString(2);
            	String password = rs.getString(3);
            	boolean enabled = rs.getBoolean(4);
            	String nombre =  rs.getString(5);
            	String apellidos =  rs.getString(6);
            	Date fechaNacimiento = rs.getTimestamp(7);
            	String sexo = rs.getString(8);
            	Date fechaAlta = rs.getTimestamp(9);
            	String husoHorario = rs.getString(11); 
            	String correoElectronico = rs.getString(12);
            	
            	return new SecurityUser(username, password, enabled, true, true, true, AuthorityUtils.NO_AUTHORITIES, 
            			userId, nombre, apellidos,fechaNacimiento, sexo, fechaAlta, null, correoElectronico, husoHorario, null ); 
            }
        });
    }

    protected UserDetails createUserDetails(String username, UserDetails userFromUserQuery,
            List combinedAuthorities) {

    	SecurityUser securityUser = (SecurityUser)userFromUserQuery;
    	return new SecurityUser( 
    			securityUser.getUsername(), 
    			securityUser.getPassword(), 
    			securityUser.isEnabled(), true, true, true, combinedAuthorities, 
    			securityUser.getUserId(),
    			securityUser.getNombre(),
    			securityUser.getApellidos(),
    			securityUser.getFechaNacimiento(),
    			securityUser.getSexo(),
    			securityUser.getFechaAlta(),
    			securityUser.getFechaModificacion(),
    			securityUser.getCorreElectronicoPpal(),
    			securityUser.getHusoHorario(),
    			securityUser.getDefaultLang()
    			);
    }
}

La clase SecurityContextFacade

Finalmente, necesitaremos crear una capa que nos permita interactuar con las clases de Spring de manera desacoplada. Esta función la cumplirá nuestra clase SecurityContextFacade. Aquí proporcionaremos una serie de métodos estáticos para acceder a la información de la capa de seguridad.

El método getAuthenticatedUser par recuperar la información del usuario conectado, y hasAuthenticatedUserRole para saber si un usuario tiene determinada authority o rol asociado.

package com.reor.app01.security;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

import com.reor.app01.type.AllowedAuthorities;

public class SecurityContextFacade {


	public static SecurityUser getAuthenticatedUser() {
		
		Object user = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
		
		if (user instanceof SecurityUser) {
			return ((SecurityUser)user);
		} else {
			return null;
		}
	}	
	
	public static boolean hasAuthenticatedUserRole(AllowedAuthorities role) {
		
		for (GrantedAuthority authority : getAuthenticatedUser().getAuthorities()) {
			if (authority.getAuthority().equals(role.toString())) {
				return true;
			}
		}
		return false;
	}
}

Terminos Tecnología: