In Java, Jboss Seam, JSF, Programação

Autenticação com Jboss Seam

Posted May 22nd, 2008 by Rodrigo Lazoti.

O frameword Jboss Seam facilita muito o desenvolvimento, recentemente precisei incluir uma rotina de autenticação em um projeto que utiliza o seam 2.0 e achei bem tranquilo a forma de se fazer esta implementação.

Para fazer isso basta criar uma Seam Entity chamada Usuario, adicionei quatro atributos: id, nome, login e senha.

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "USUARIO")
public class Usuario implements Serializable {

private Long id;
private String nome;
private String login;
private String senha;

@Id
@Column(name = "USUARIO_ID")
public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

@Column(name="NOME", length=50)
public String getNome() {
return nome;
}

public void setNome(String nome) {
this.nome = nome;
}

@Column(name="SENHA", length=64)
public String getSenha() {
return senha;
}

public void setSenha(String senha) {
this.senha = senha;
}

@Column(name="LOGIN", length=25)
public String getLogin() {
return login;
}

public void setLogin(String login) {
this.login = login;
}
}

Na Seam Action chama UsuarioList que foi gerada pelo seam, inclui um método para fazer a pesquisa de usuário pelo seu login e senha:

import java.security.NoSuchAlgorithmException;

import org.jboss.seam.annotations.Name;
import org.jboss.seam.framework.EntityQuery;

import com.seedts.rfid.entity.Usuario;
import com.seedts.rfid.util.Criptografia;
import com.seedts.rfid.util.UtilException;

@Name("usuarioList")
public class UsuarioList extends EntityQuery {
@Override
public String getEjbql() {
return "select usuario from Usuario usuario";
}

public Usuario login(String login, String senha) {
Usuario usuario = (Usuario) this.getEntityManager().createQuery(
"select u from Usuario as u where u.login = :login")
.setParameter("login", login)
.getSingleResult();

if (usuario.getSenha().equals(senha))
return usuario;
else
return null;
}
}

E para finalizar basta alterar o método authenticate() da classe Authenticator que também é gerada pelo seam:

import java.security.NoSuchAlgorithmException;

import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.contexts.Contexts;
import org.jboss.seam.faces.FacesMessages;
import org.jboss.seam.log.Log;
import org.jboss.seam.security.Identity;

import com.seedts.rfid.entity.Usuario;
import com.seedts.rfid.util.UtilException;

@Name("authenticator")
public class Authenticator {
@Logger
Log log;

@In
Identity identity;

@In
FacesMessages facesMessages;

public boolean authenticate() throws NoSuchAlgorithmException, UtilException {

Usuario usuario = new UsuarioList().login(identity.getUsername(), identity.getPassword());

if (usuario != null) {
Contexts.getSessionContext().set("usuario", usuario);
identity.addRole("admin");
return true;

}
else
return false;
}
}

E com isso a autenticação básica do projeto já esta funcionando.

Related Posts

  1. Testes unitários com TestNG
  2. Gerador de senhas aleatórias em java

10 responses to Autenticação com Jboss Seam

  1. ukaliko says:

    Muito massa o artigo Rodrigo. Ja progroma em ja e estou iniciando agora no JbossSeam e fazendo um teste, testei o codigo que vc postou aqui, mas ta acontecendo algo de estranho porque toda vez que subo a aplicação (Projeto JbossSeam) ele recria a tabela usuario, apagando o usuario que ja havia cadastrado, o que pode estar acontecendo?…valeu cara um abraço.

  2. Rodrigo Lazoti says:

    Obrigado por visitar o blog.

    Veja se no seu persistence.xml a propriedade “hibernate.hbm2ddl.auto” esta como “create” ou “update”, para que a tabela não seja recriada toda vez que o app server seja iniciado esta propriedade deve ser igual a “update”.

    []‘s

  3. ukaliko says:

    E ai Rodrigo. valeu a dica.
    Fiz o que voce citou, funcionou bacaninha. Agora iniciei o cadastro de usuario pra testar crud e esta dando o erro abaixo, já dei uma pescada na net, mas não encontrei nada que realmente ajuda-se a resolver o problema.
    se sabe o que pode ser? Valeu Rodrigo.

    org.jboss.seam.InstantiationException: Could not instantiate Seam component: webmascoli11EntityManagerFactory
    at org.jboss.seam.Component.newInstance(Component.java:1986)
    at org.jboss.seam.contexts.Contexts.startup(Contexts.java:304)
    at org.jboss.seam.contexts.Contexts.startup(Contexts.java:278)
    at org.jboss.seam.contexts.ServletLifecycle.endInitialization(ServletLifecycle.java:95)
    at org.jboss.seam.init.Initialization.init(Initialization.java:596)

  4. ukaliko says:

    Então Rodrigo!! Descobri o que estava provocando o erro.
    Faltava configurar o JNDI corretamente para apontar para minha aplicação.
    troquei a linha:

    do arquivo components.xml para:

    Ai funcionou belezinha :) .

    Valeu.

  5. Eduardo says:

    Rodrigo,

    Você tem algum exemplo de autenticação por LDAP usando o Seam Framework?

    Att.

  6. Gilson Damaso says:

    sou novato, gostaria de saber qual seria a senha e o login??? abraço e aguardo

  7. Cristiano Pires says:

    Rodrigo, estou usando seam com tomcat, funciona tudo, só que qdo eu tento fazer logon, ele loga, retorna true, só que dá login failed. Não consegui identificar por que… Já passou por isso?

  8. Rodrigo Lazoti says:

    Cristiano, tudo bem?

    Já tentou debugar a aplicação e ver se não tem algo de anormal ocorrendo? Assim de cara não tenho ideia do que pode ser.

    []‘s

  9. Cristiano Pires says:

    Já debuguei. O erro ocorre na classe Identity.class do seam, na linha 261. Ele tenta verificar se já está logado após a execução do método autenticate();, mas ele retorna falso. Parece um erro do seam. Veja o trecho de código da classe Identity:

    public String login()
    {
    try
    {
    if (isLoggedIn())
    {
    // If authentication has already occurred during this request via a silent login,
    // and login() is explicitly called then we still want to raise the LOGIN_SUCCESSFUL event,
    // and then return.
    if (Contexts.isEventContextActive() && Contexts.getEventContext().isSet(SILENT_LOGIN))
    {
    if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGIN_SUCCESSFUL);
    return “loggedIn”;
    }

    if (Events.exists()) Events.instance().raiseEvent(EVENT_ALREADY_LOGGED_IN);
    return “loggedIn”;
    }

    authenticate(); //aqui ele faz o logon com a role que eu enviei, no caso admin

    if (!isLoggedIn()) //aqui nesse método, deveria retornar valor true se a interface ‘principal’ tiver o valor admin. No caso, quando eu debugue ela tem esse valor, mas retorna como falso, aí gera a excessão.
    {
    throw new LoginException();
    }

    if ( log.isDebugEnabled() )
    {
    log.debug(“Login successful for: ” + getCredentials().getUsername());
    }

    if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGIN_SUCCESSFUL);
    return “loggedIn”;
    }
    catch (LoginException ex)
    {
    credentials.invalidate();

    if ( log.isDebugEnabled() )
    {
    log.debug(“Login failed for: ” + getCredentials().getUsername(), ex);
    }
    if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGIN_FAILED, ex);
    }

    return null;
    }

    Aqui, o método autenticate() e métodos dependentes:

    protected void authenticate(LoginContext loginContext)
    throws LoginException
    {
    try
    {
    authenticating = true;
    preAuthenticate();
    loginContext.login();
    postAuthenticate();
    }
    finally
    {
    // Set password to null whether authentication is successful or not
    credentials.setPassword(null);
    authenticating = false;
    }
    }

    /**
    * Clears any roles added by calling addRole() while not authenticated.
    * This method may be overridden by a subclass if different
    * pre-authentication logic should occur.
    */
    protected void preAuthenticate()
    {
    preAuthenticationRoles.clear();
    if (Events.exists()) Events.instance().raiseEvent(EVENT_PRE_AUTHENTICATE);
    }

    /**
    * Extracts the principal from the subject, and populates the roles of the
    * authenticated user. This method may be overridden by a subclass if
    * different post-authentication logic should occur.
    */
    protected void postAuthenticate()
    {
    // Populate the working memory with the user’s principals
    for ( Principal p : getSubject().getPrincipals() )
    {
    if ( !(p instanceof Group))
    {
    if (principal == null)
    {
    principal = p;
    break;
    }
    }
    }

    if (!preAuthenticationRoles.isEmpty() && isLoggedIn())
    {
    for (String role : preAuthenticationRoles)
    {
    addRole(role);
    }
    preAuthenticationRoles.clear();
    }

    credentials.setPassword(null);

    if (Events.exists()) Events.instance().raiseEvent(EVENT_POST_AUTHENTICATE, this);
    }

    protected LoginContext getLoginContext() throws LoginException
    {
    if (getJaasConfigName() != null)
    {
    return new LoginContext(getJaasConfigName(), getSubject(),
    credentials.createCallbackHandler());
    }

    return new LoginContext(Configuration.DEFAULT_JAAS_CONFIG_NAME, getSubject(),
    credentials.createCallbackHandler(), Configuration.instance());
    }

    public void logout()
    {
    if (isLoggedIn())
    {
    unAuthenticate();
    Session.instance().invalidate();
    if (Events.exists()) Events.instance().raiseEvent(EVENT_LOGGED_OUT);
    }
    }

    Confesso que estou um tando confuso quanto a este erro. Pior que não achei nada no google. Parece que ninguém passou por isso… esquesito…

  10. Cristiano Pires says:

    Só pra finalizar a dúvida. Já corrigi. O problema era de configuração do tomcat. Já resolvi. Refiz todo o procedimento do tomcat com seam do zero e tudo funcionou. Mas fica a dica!

Leave a response: