Tabla de Contenidos

Autenticación en Fundeweb 2.0

PEDRO DELGADO YARZA 2014/01/29 13:51

Es obligatorio realizar las modificaciones indicadas en la siguiente guía:

Actualización del Sistema de Autenticación de Aplicaciones FundeWeb

Mecanismo de Autenticación

En Fundeweb 2.0 se ha dispuesto de un mecanismo de autenticación múltiple que dispone de una serie de métodos de autenticación implementados por defecto y nos permite añadir nuevos mecanismos para ampliar la funcionalidad del componente en caso de ser necesario. Los mecanismos existentes por defecto son los siguientes:

Este mecanismo se dispone en la clase AuthenticationManagerBean (que tiene que extender la clase AbstractAuthenticationManagerBean) en la cual según el método de autenticación que hayamos seleccionado, se lanzan las librerías necesarias para realizar la autenticación.

El siguiente código es el encargado de obtener la factoría de autenticación necesaria en cada caso.

    protected AuthenticationFactory getFactoria(AuthenticationType authenticationType) {
        if (authenticationType == null) {
            activateCredentialsUmu( this.defaultAuthenticationType );
        }
        switch (authenticationType) {
            case CARD: {
                return new AuthenticationFactoryCard();
            }
            case CERTIFICATE: {
                return new AuthenticationFactoryCertificateSSL();
            }
            case NIF: {
                return new AuthenticationFactoryNif();
            }
            case RADIUS: {
                return new AuthenticationFactoryRadius();
            }
            case SSO: {
                return new AuthenticationFactorySSO();
            }
            default: {
                return this.defaultAuthenticationFactory;
            }
        }
    }

La estructura de una factoría consta de dos métodos:

El código de la factoría quedaría así:

    public class AuthenticationFactoryRadius implements AuthenticationFactory {
 
	public AuthenticationMethod createAuthenticationMethod() {
		return new AuthenticationMethodRadius();
	}
 
	public CredentialsUmu createCredentials() {
		return new CredentialsDefaultUmu();
	}
 
    }

Añadir nuevo método de autenticación

Si deseáramos ampliar la funcionalidad de Fundeweb 2.0 añadiendo un nuevo método de autenticación deberemos realizar lo siguiente:

    public enum AuthenticationType {
        RADIUS, CARD, CERTIFICATE, NIF, SSO
    }
    protected String getAuthenticationTypeLabel(AuthenticationType authenticationType) {
        ResourceBundle srb = SeamResourceBundle.getBundle();
 
        try {
            switch (authenticationType) {
                case CARD: {
                    return srb.getString("label.tipo_acceso_tarjeta");
                }
                case CERTIFICATE: {
                    return srb.getString("label.tipo_acceso_certificado");
                }
                case NIF: {
                    return srb.getString("label.tipo_acceso_nif");
                }
                case RADIUS: {
                    return srb.getString("label.tipo_acceso_correo");
                }
                case SSO: {
                    return srb.getString("label.tipo_acceso_sso");
                }
                default:
                    return this.defaultAuthenticationTypeLabel;
            }
        } catch (MissingResourceException mre) {
            LOG.error("Error al obtener las etiquetas para los tipos de autenticacion.", mre);
        }
        return "";
    }
    @Override
    public void preAuthenticate() {
        try {
            // Vuestro código para asignar los datos a la credencial
            getIdentity().getCredentials().setUsername("miusuario@um.es");
        } catch (Throwable t) {
            LOG.error("Error inesperado.", t);
        }
    }
 
    @Override
    public boolean authenticate() {
        String usuario = getIdentity().getCredentials().getUsername();
        LOG.info("Autenticando a: #0", usuario);
        if (!UtilString.esCadenaVacia(usuario) && !usuario.contains("@")) {
            usuario += "@um.es";
        }
        if ("invitado@um.es".equals(usuario) && "bienvenido".equals(getIdentity().getCredentials().getPassword())) {
            return true;
        }
        try {
            .....
            .....
            .....
            .....
        } catch (ServiceNotFoundException snfe) {
            LOG.error("Error al buscar un servicio", snfe);
        } catch (PersonaException pe) {
            LOG.error("Error: al obtener los datos del Usuario en GENTE.", pe);
            processErrorMessage();
        } catch (PersonaNotFoundException pnfe) {
            LOG.error("Error: el usuario no se encuentra en GENTE.", pnfe);
            processErrorMessage();
        }
        return false;
    }
 
    @Override
    public void postAuthenticate() {
        try {
            // Vuestro código para realizar acciones después de la autenticación
            // y antes de lanzarse los eventos "org.jboss.seam.security.loginSuccessful"
            // o "org.jboss.seam.security.loginFailed"
        } catch (Throwable t) {
            LOG.error("Error inesperado.", t);
        }
    }

Tras estos pasos ya tendremos registrado y listo para usar nuestro nuevo mecanismo de autenticación.

También podemos extender o modificar algunos de los sistemas de autenticación ya creados.

Autenticación Personalizada

Podemos personalizar los métodos de autenticación y las credenciales que estan disponibles por defecto en las aplicaciones FundeWeb. En la factoria correspondiente al sistema de autenticación, aparecen las constantes para designar los nombres de el método de autenticación y la credencial. A continuación un ejemplo para personalizar el método de autenticación con NIF.

Autenticación con NIF Personalizada


Podemos personalizar la autenticación con NIF (DNI/NIF/NIE) siguiendo los siguientes pasos:

Código de ejemplo:

package es.um.atica.prueba.security.authentication.method;
 
 
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.log.Log;
import org.jboss.seam.log.Logging;
import org.umu.atica.servicios.gesper.gente.exceptions.PersonaException;
import org.umu.atica.servicios.gesper.gente.exceptions.PersonaNotFoundException;
 
import buscador.servicios.exceptions.ServiceNotFoundException;
import es.um.atica.seam.security.authentication.factories.AuthenticationFactoryNif;
import es.um.atica.seam.security.authentication.method.AuthenticationMethod;
 
@Name(AuthenticationFactoryNif.AUTHENTICATION_METHOD_NIF_COMPONENT_NAME)
@BypassInterceptors
public class PruebaAuthenticationMethodNif extends AuthenticationMethod {
 
    private static final Log LOG = Logging.getLog(PruebaAuthenticationMethodNif.class);
 
    @Override
    public boolean authenticate() {
        try {
            this.loadUser( getCredentials().getUsername() );
            LOG.info("Autenticando a: #0 - #1", getCredentials().getUsername(),
                     getUmuIdentity().getPersona().getCorreo());
 
            // TODO logicapara la verificacion de las credenciales de autenticacion
 
            return ...;
        } catch (ServiceNotFoundException snfe) {
            LOG.error("Error al buscar un servicio", snfe);
        } catch (PersonaException pe) {
            LOG.error("Error: al obtener los datos del Usuario en GENTE.", pe);
            processErrorMessage();
        } catch (PersonaNotFoundException pnfe) {
            LOG.error("Error: el usuario no se encuentra en GENTE.", pnfe);
            processErrorMessage();
        } catch ( Throwable t ) {
            LOG.error("Error inesperado.", t);
        }
        return false;
    }
 
    @Override
    protected void loadUser(Object identifier) throws Exception {
        // TODO Cargar los datos del usuario (no permisos)
 
        // Este método carga los datos de la persona en base al DNI de Gente
        this.loadPersonaByIdentificador( (String) identifier );
    }
 
    /*
     * (non-Javadoc)
     * @see es.um.atica.util.FundeWebManager#getLog()
     */
    @Override
    protected Log getLog() {
        return LOG;
    }
 
}

Para otros métodos de autenticación, hay que utilizar la factoria relacionada.