Tutorial de JAAS

40 respostas
F

1 - Introdução

Pra começar, o Jaas é uma implementação do padrão de segurança do j2ee.
Serve para controlar permissões de vários tipos: arquivos, diretórios, conteúdos, url’s…

Para web, basta seguir os passos abaixo.
Quando usamos este padrão de segurança,
devemos estar cientes que este modulo está a nível de servidor de aplicação e não de aplicação,
ou seja, este modulo de autenticação será executado pelo servidor de aplicação,
antes mesmo de acessar a aplicação.

2 - Criação do modulo de login
Existe uma interface definida no j2ee que é usada para efetuar o login.
javax.security.auth.spi.LoginModule
Devemos implementá-la, conforme o exemplo abaixo.

package br.com.guj.security.principals;
import java.security.Principal;
import java.util.Set;

/**
 * @author fabio.viana
 */
public class User implements Principal{
	private String name;
	private Set roles;
	
	public User(String name){
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
	
	public Set getRoles() {
		return roles;
	}

	public void setRoles(Set roles) {
		if (this.roles == null)
			this.roles = roles;
	}
}



package br.com.guj.security.principals;
import java.security.Principal;

/**
 * @author fabio.viana
 */
public class Role implements Principal{
	private String name;
	
	public Role(String name){
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
}



package br.com.guj.security;
import java.sql.*;
import java.util.*;
import javax.naming.*;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;
import br.com.guj.security.principals.*;

/**
 * @author fabio.viana
 */
public class GujLoginModule implements LoginModule {
	private boolean commitSucceeded = false;
	private boolean succeeded = false;

	private User user;
	private Set roles = new HashSet();

	protected Subject subject;
	protected CallbackHandler callbackHandler;
	protected Map sharedState;
	private String dataSourceName;
	private String sqlUser;
	private String sqlRoles;

	public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
		this.subject = subject;
		this.callbackHandler = callbackHandler;
		this.sharedState = sharedState;
		dataSourceName = (String) options.get("dataSourceName");
		sqlUser = (String) options.get("sqlUser");
		sqlRoles = (String) options.get("sqlRoles");
	}

	public boolean login() throws LoginException {
		// recupera o login e senha informados no form
		getUsernamePassword();

		Connection conn = null;
		try {
			// obtem a conexão
			try {
				Context initContext = new InitialContext();
				Context envContext = (Context) initContext.lookup("java:/comp/env");
				DataSource ds = (DataSource) envContext.lookup(dataSourceName);
				conn = ds.getConnection();
			} catch (NamingException e) {
				succeeded = false;
				throw new LoginException("Erro ao recuperar DataSource: " + e.getClass().getName() + ": " + e.getMessage());
			} catch (SQLException e) {
				succeeded = false;
				throw new LoginException("Erro ao obter conexão: " + e.getClass().getName() + ": " + e.getMessage());
			}
			// valida o usuario
			validaUsuario(conn);
		} finally {
			if (conn != null) {
				try {
					conn.close();
				} catch (SQLException e) {
				}
			}
		}
		// acidiona o usuario e roles no mapa de compartilhamento
		sharedState.put("javax.security.auth.principal", user);
		sharedState.put("javax.security.auth.roles", roles);

		return true;
	}

	public boolean commit() throws LoginException {
		// adiciona o usuario no principals
		if (user != null && !subject.getPrincipals().contains(user)) {
			subject.getPrincipals().add(user);
		}
		// adiciona as roles no principals
		if (roles != null) {
			Iterator it = roles.iterator();
			while (it.hasNext()) {
				Role role = (Role) it.next();
				if (!subject.getPrincipals().contains(role)) {
					subject.getPrincipals().add(role);
				}
			}
		}
		
		commitSucceeded = true;
		return true;
	}

	public boolean abort() throws LoginException {
		if (!succeeded) {
			return false;
		} else if (succeeded && !commitSucceeded) {
			succeeded = false;
		} else {
			succeeded = false;
			logout();
		}

		this.subject = null;
		this.callbackHandler = null;
		this.sharedState = null;
		this.roles = new HashSet();

		return succeeded;
	}

	public boolean logout() throws LoginException {
		// remove o usuario e as roles do principals
		subject.getPrincipals().removeAll(roles);
		subject.getPrincipals().remove(user);
		return true;
	}
	/**
	 * Valida login e senha no banco
	 */
	private void validaUsuario(Connection conn) throws LoginException {
		String senhaBanco = null;
		PreparedStatement statement = null;
		ResultSet rs = null;
		try {
			statement = conn.prepareStatement(sqlUser);
			statement.setString(1, loginInformado);
			rs = statement.executeQuery();
			if (rs.next()) {
				senhaBanco = rs.getString(1);
			} else {
				succeeded = false;
				throw new LoginException("Usuário não localizado.");
			}
		} catch (SQLException e) {
			succeeded = false;
			throw new LoginException("Erro ao abrir sessão: "
					+ e.getClass().getName() + ": " + e.getMessage());
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (statement != null)
					statement.close();
			} catch (Exception e) {

			}
		}

		if (senhaInformado.equals(senhaBanco)) {
			user = new User(loginInformado);
			recuperaRoles(conn);
			user.setRoles(roles);
			return;
		} else {
			throw new LoginException("Senha Inválida.");
		}
	}
	/**
	 * Recupera as roles no banco
	 */
	public void recuperaRoles(Connection conn) throws LoginException {
		PreparedStatement statement = null;
		ResultSet rs = null;
		try {
			statement = conn.prepareStatement(sqlRoles);
			statement.setString(1, loginInformado);
			rs = statement.executeQuery();
			while (rs.next()) {
				roles.add(new Role(rs.getString(1)));
			}
			roles.add(new Role("LOGADO"));
		} catch (SQLException e) {
			succeeded = false;
			throw new LoginException("Erro ao recuperar roles: " + e.getClass().getName() + ": " + e.getMessage());
		} finally {
			try {
				if (rs != null)
					rs.close();
				if (statement != null)
					statement.close();
			} catch (Exception e) {

			}
		}
	}

	/**
	 * Login do usuário.
	 */
	protected String loginInformado;

	/**
	 * Senha do usuário.
	 */
	protected String senhaInformado;

	/**
	 * Obtem o login e senha digitados
	 */
	protected void getUsernamePassword() throws LoginException {
		if (callbackHandler == null)
			throw new LoginException("Error: no CallbackHandler available to garner authentication information from the user");

		Callback[] callbacks = new Callback[2];
		callbacks[0] = new NameCallback("Login");
		callbacks[1] = new PasswordCallback("Senha", false);
		try {
			callbackHandler.handle(callbacks);
			loginInformado = ((NameCallback) callbacks[0]).getName();
			char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword();
			senhaInformado = new String(tmpPassword);
			((PasswordCallback) callbacks[1]).clearPassword();
		} catch (java.io.IOException ioe) {
			throw new LoginException(ioe.toString());
		} catch (UnsupportedCallbackException uce) {
			throw new LoginException("Error: " + uce.getCallback().toString() + " not available to garner authentication information from the user");
		}
	}
}

O método initialize() é invocado sempre que uma nova autenticação é solicitada.
São passados como parametros o Subject, CallbackHandler, o mapa de objetos compartilhados
e o mapa de opções do login.config (sessão 3). O mais importante destes parametros para nós será o options,
pois nele receberemos os parametros de sql e datasource.
O método login() é invocado quando é enviado os dados (login e senha) de autenticação.
O método commit() é invocado quando o login() obtém sucesso.
O método abort() é invocado quando o login() não obtém sucesso.
O método logout() é invocado quando o usuário desloga da aplicação.

Agora, com as classes de login criadas, devemos gerar um jar e adicionar no classpath do servidor de aplicação.
No tomcat, basta colocar o jar em $CATALINA_HOME/common/lib.

Obs.: Principal é a interface usada para acessar o login (no caso da classe User) e a role (no caso da classe Role)

3- Configurações
Devemos agora configurar o nosso login.
Para que o servidor de aplicação use nosso modulo de login, devemos criar um arquivo (login.config) contendo as informações necessárias para carregar o modulo.
Ele deve ter o seguinte formato:

NOME_DO_MODULO{
	CLASSE_DE_LOGIN_1 (requerid) (parametro1=valor1..parametroN=valorN);
	CLASSE_DE_LOGIN_2 (requerid) (parametro1=valor1..parametroN=valorN);
}

O flag requerid, indica se a autenticação naquela classe é requerida.
Podemos ter vários validadores de login (classe LoginModule) para o mesmo modulo de login.
Caso queira-se autenticar no banco e no ldap, basta implementar o LoginModule pra cada um e colocar no login.config.

No nosso exemplo ficaria assim:

guj {
	br.com.guj.security.GujLoginModule required
		dataSourceName="jdbc/GUJ"
		sqlUser="select senha from tb_usuario where login=?"
		sqlRoles="select id_role from tb_usuario_roles where login=?"
	;
};

Apartir de agora, toda vez que iniciarmos o servidor de aplicação, será necessário informar o arquivo de configuração, desta forma:
-Djava.security.auth.login.config=$CATALINA_HOME/conf/login.config

Até aqui, o servidor de aplicação já estará configurado com nosso modulo.

4- Segurança na aplicação
Agora temos que adicionar a segurança em nossa aplicação.
Para que nossa aplicação faça uso do modulo de segurança, devemos adicionar um realm no contexto.

<Realm className="org.apache.catalina.realm.JAASRealm"
	appName="guj" 
	userClassNames="br.com.guj.security.principals.User" 
	roleClassNames="br.com.guj.security.principals.Role" 
	debug="99"/>

Este parametro appName se refere ao NOME_DO_MODULO.

Agora basta adicionar as restrições da nossa aplicação. Isto é feito no web.xml. Veja abaixo:

...
	<!-- Restrições -->
	<security-constraint>
		<display-name>cadastro de cientes</display-name>
		<web-resource-collection>
			<web-resource-name>cadastro de cientes</web-resource-name>
			<url-pattern>/cliente.do</url-pattern>
		</web-resource-collection>
		<auth-constraint>
			<role-name>ADM</role-name>
			<role-name>CAD_CLIENTE</role-name>
		</auth-constraint>
	</security-constraint>
	
	<security-constraint>
		<display-name>help da app</display-name>
		<web-resource-collection>
			<web-resource-name>help da app</web-resource-name>
			<url-pattern>/help.do</url-pattern>
		</web-resource-collection>
		<auth-constraint>
			<role-name>LOGADO</role-name>
		</auth-constraint>
	</security-constraint>
...
	<!-- Lista de Roles -->
	<security-role>
		<description>Quando usuario estiver logado</description>
		<role-name>LOGADO</role-name>
	</security-role>
	
	<security-role>
		<description>Administrador, pode fazer tudo</description>
		<role-name>ADM</role-name>
	</security-role>
	
	<security-role>
		<description>Para cadastrar cliente, deve se ter esta role</description>
		<role-name>CAD_CLIENTE</role-name>
	</security-role>

Repare que a url /cliente.do possue duas roles, será avaliado se o usuario posue alguma delas.
Repare tambem que foi criado uma role LOGADO. Ela serve pra validar aquelas url’s que basta que o usuario esteje logado.

Agora só falta criar o formulário de login.
Crie um arquivo para o formulario (login.jsp). Observe abaixo o exemplo.

<form method="POST" action="<%=request.getContextPath()%>/j_security_check">
	Usuário:&nbsp;<input type="text" name="j_username" size="15"><br>
	Senha:&nbsp;<input type="password" name="j_password" maxlength="20" size="15">
</form>

Sempre coloque os nomes dos campos de login e senha como j_username e j_password.
Este j_security_check é apenas para que o servidor de aplicação identifique que se trata de uma tentativa de login.

Crie tambem um arquivo de erro (erro.jsp).

Usuario ou senha inválido(s).<br>
<form method="POST" action="<%=request.getContextPath()%>/j_security_check">
	Usuário:&nbsp;<input type="text" name="j_username" size="15"><br>
	Senha:&nbsp;<input type="password" name="j_password" maxlength="20" size="15">
</form>

Para concluir, adicione mais esta configurão no web.xml. Trata-se do mapeamento dos arquivos login.jsp e erro.jsp

<login-config>
		<auth-method>FORM</auth-method>
		<realm-name>default</realm-name>
		<form-login-config>
			<form-login-page>/login.jsp</form-login-page>
			<form-error-page>/erro.jsp</form-error-page>
		</form-login-config>
	</login-config>

Pronto!

Quando for acessado a url /cliente.do, o servidor de aplicação irá identificar que é necessário autenticação,
se não foi feita anteriromente ele irá redirecionar para a pagina de login até que o usuario seja autenticado.

5- Conclusão
O jaas é um pouco limitado e cheio de restrições, mas para controlar segurança e autenticação é o mais recomendado.
Caso precise de adicionar regras na autenticação, como por exemplo expiração de senha,
use um filter só para ver se o usuario está com a senha expirada.

Caso precise do usuario autenticado e/ou a(s) role(s) em um Servlet, Action… basta usar os metodos:

HttpServletRequest.getUserPrincipal(); // retorna o User
HttpServletRequest.isUserInRole("ADM"); // retorna se o usuario possue a role informada
User user = (User)HttpServletRequest.getUserPrincipal();
user.getRoles(); // roles do usuario

Caso tenham duvidas entrem em contato.

40 Respostas

C

Porque você não escreveu um artigo no formato do guj?

F

é q não sei como fazer isso…

N

concordo no formato guj… iai fica loco…

tem meu voto

S

Apenas uma opinião pessoal. Vc não acha JAAS uma bazuka para matar uma mosca?

F

mate-a bem matado…
o bom do jaas é que vc pode programar suas actions, servlets, controllers… sem se preocupar com a segurança de acesso. basta só mapear as restrições.

B

saoj:

Apenas uma opinião pessoal. Vc não acha JAAS uma bazuka para matar uma mosca?

Como vc faz sem os JAAS?

Eu estou utilizando proxy.

So estou perguntando pq ainda n~]ao vi nenhuma aplicação saudavel de segurança.

S

A segurança pode ser controlada por um filtro que intercepta actions e/ou páginas.

No caso das páginas tb pode ser feita por tags.

Dá uma olhada aqui:

http://www.mentaframework.org/authentication.jsp

http://www.mentaframework.org/authorization.jsp

F

prefiro o padrão j2ee para segurança, visto que posso usar este mesmo modulo em qualquer plataforma, web, desktop… com independencia, inclusive sobre outras frameworks, como spring, struts, mentawai, webwork… isto porque a segurança do jaas está a nivel de servidor de aplicação e nao restritamente à aplicação.

M

E no caso de não poder usar o Mentawai? Uma solução padrão que todos os app. servers devem (ou pelo menos deveriam) implementar pode ser muito útil.

S

[color="blue]Sim. Bem-vindo ao EJB![/color] Divirta-se.

F

saoj:

Uma solução padrão que todos os app. servers devem (ou pelo menos deveriam) implementar pode ser muito útil.

[color="blue]Sim. Bem-vindo ao EJB![/color] Divirta-se.

Sergio,

Mas JAAS != EJB.

]['s

D

Mais um pro JAAS… Servidor que presta implementa SSO mas para isso tem q tah usando o JAAS… Por isso prefiro JAAS… E uma coisa que vc faz uma vez e eskece…

S

Tudo depois de feito fica fácil. De novo isso é uma questão de gosto pessoal. Eu particularmente achei o tutorial extenso, não por má-qualidade do tutorial, que por sinal está excelente pois entendi tudo, mas pela complexidade do JAAS.

E como ele suporta autorização de apenas um pedaço dentro da página? E como ele suporta redirecionamento depois do login? Deve suportar… Outro tutorial? :slight_smile:

Acho que a tendencia atual é ir contra tudo que não é simples. Se um conta-gotas mata a mosca então use o conta-gotas e não a bazuka. JAAS e EJB já tiveram seu momento. Bom… Minha humilde opinião… Vide a hype de RoR e tirem suas conclusões…

G

Conclusão retirada do livro ‘Java Development with Spring Framework’, na parte que fala sobre Acegi Security, logo depois de mostrar as vantagens do uso do JAAS:

“Certainly JAAS is an important standard when developing applications intended for a limited privilege execution environment, such as an applet. However, unless web and EJB container support for JAAS greatly improves, it is unlikely to prove practical for efficiently developing portable, secure enterprise applications.”

Quem não tem o livro, achei um pdf perdido no google, nesse endereço:
http://searchappsecurity.techtarget.com/searchAppSecurity/downloads/Spring_Framework_ch10.pdf

Para quem não conhece direito JAAS, é interessante de se ler, e principalmente saber quando se deve usar isso. Sabendo usar quando necessário, não há mal nenhum. O problema é usar para “matar uma mosca”, como já disseram… :smiley:

F

para fazer autorizações em pedações da pagina com jaas é só fazer assim:

<%
if (request.isUserInRole("admins") && request.isUserInRole("managers")){ 
%>
Only authorized people can see this.
<%
}
%>
<%
if (request.isUserInRole("create")){ 
%>
Only authorized people can see this.
<%
}
%>

mas se não quiser usar scriptlets, crie uma tagfile ou taglib.

S

Tudo bem, mas tem que fazer uma tag pra isso. Código no meio de JSP hoje em dia não dá mais para aceitar…

F

depois vou escrever um tutorial de taglib e tagfile…

O

Optem sempre pelo padrão JAAS, por várias razões:

  • padrão industrial para TODOS (atualmente +de 50) os AppServer Java Enterprise

  • não precisa ser homologado individualmente (algumas empresas não aceitam software OpenSource em ambientes produtivos)

  • aderente ao SSO usando atualmente no mercado

  • TOTALMENTE DESCRITIVO (não é necessário alterar código para mudar a relação usuário-grupo-permissão).

Excelente tópico.

F

obrigado!
virá mais… aguardem…

M

Viva,

consigo fazer o login com o JAASRealm. Mas estou não estou a usar o login com FORM mas sim com BASIC. Estou a usar uma servlet com session.invalidate(). Não me aparece a janela realm de autenticação depois de fazer o logout…alguém me pode dizer qual é o meu erro?

Cumprimentos,

Mazarama

D

Onde eu adiciono o arquivo de configuração b[/b].
Na minha aplicação, implementei a classe de LoginModule, web.xml, JSPs, adicionei o Realm no server.xml(com as devidas configurações do BD), etc… mas esse arquivo nãio sei onde colocar…
Alguém poderia me ajudar ???

J

Olá a todos,

Só estou postando para agradecer a boa vontade do fviana em criar esse tutorial.
Meus parabéns. Espero poder ajudar desta forma ou de outra assim que possível.

L

Ola pessoal!
Sabem dizer-me como posso aplicar o logout(), isto é, como posso chamar essa função em html ou numa servlet?
Obrigado

R

Como pego o tipo de Erro/Exception da autenticação no meu jsp de resultado??

Por exemplo:

1 - Senha errada!
2 - Senha vencida!
3 - Primeira vez que acessa -> troque a senha!
4 …

L

luisilvaJAVA:
Ola pessoal!
Sabem dizer-me como posso aplicar o logout(), isto é, como posso chamar essa função em html ou numa servlet?
Obrigado

session.invalidate()

E

Pessoal dúvida simples, de onde vem os outros paramentros para a conexão com o banco tipo usuario, senha, …? Antes que me esqueça um otimo tutorial, valeu.

dataSourceName="jdbc/GUJ"

Esqueleto

L
public void doLogout(ActionEvent event) throws IOException{
	     final HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
	     request.getSession( false ).invalidate();	
             FacesContext.getCurrentInstance().getExternalContext().redirect("/aplicacao");
	}
M

Cara, alguém conseguiu fazer isso funcionar assim como está descrito? Tive que fazer um grupo de Roles implementando Group e adicionando Role ao grupo.
tipo:

grupoRole.addMember(new Role("admin'));
 grupoRole.addMember(new Role("logado));
 subject.getPrincipals().add(UsuarioPrincipal("teste"));
 subject.getPrincipals().add(grupoRole);

Queria saber como auntenticar em um WebService via swing. Alguém ai sabe?

C

Pessoal,

implementei seguindo este tutorial com a classe GujLoginModule tudo direitinho.

Coloquei logs e ele esta chamando o método login, validando o usuário e no final chamando o método commit() certinho.

Quando ele terminar o método commit retorna para tela a seguinte mensagem :

HTTP Status 403 - Access to the requested resource has been denied

Alguém sabe me dizer por que?

Obrigado

M

Cgneo, ninguém respondeu a minha duvida, mas acredito que seja pelo mesmo motivo que tive que criar um grupo de roles chamado Roles conforme descrito

C

Amigo,

fiz o que você falou mas mesmo assim deu erro 403.

Estou a seguir colocando a classe que implementei, esta cheio de log, pois estava analisando por onde passou. O engraçado que ele vai até o commit certinho.

Tem como você me enviar o seu código desta classe para comparar.

import java.sql.Connection;

import java.sql.PreparedStatement;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.util.HashSet;

import java.util.Iterator;

import java.util.Map;

import java.util.Set;
import javax.naming.Context;

import javax.naming.InitialContext;

import javax.naming.NamingException;

import javax.security.auth.Subject;

import javax.security.auth.callback.Callback;

import javax.security.auth.callback.CallbackHandler;

import javax.security.auth.callback.NameCallback;

import javax.security.auth.callback.PasswordCallback;

import javax.security.auth.callback.UnsupportedCallbackException;

import javax.security.auth.login.LoginException;

import javax.security.auth.spi.LoginModule;

import javax.sql.DataSource;
public class GujLoginModule implements LoginModule {

private boolean commitSucceeded = false;

private boolean succeeded = false;
private User user;
private Set roles = new HashSet();

private GroupRole grupoRole = new GroupRole("abc");

protected Subject subject;
protected CallbackHandler callbackHandler;
protected Map sharedState;
private String dataSourceName;
private String sqlUser;
private String sqlRoles;

public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
	System.err.println("1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + callbackHandler);
	this.subject = subject;
    this.callbackHandler = callbackHandler;
    this.sharedState = sharedState;
    dataSourceName = (String) options.get("dataSourceName");
    sqlUser = (String) options.get("sqlUser");
    sqlRoles = (String) options.get("sqlRoles");
}

public boolean login() throws LoginException {
	System.err.println("2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    // recupera o login e senha informados no form
    getUsernamePassword();

    Connection conn = null;
    try {
        // obtem a conexão
        try {
            Context initContext = new InitialContext();

// Context envContext = (Context) initContext.lookup(“java:/comp/env”);
// DataSource ds = (DataSource) envContext.lookup(dataSourceName);

DataSource ds = (DataSource) initContext.lookup(dataSourceName);
            conn = ds.getConnection();
        } catch (NamingException e) {
        	System.err.println("2 NamingException");
            succeeded = false;
            throw new LoginException("Erro ao recuperar DataSource: " + e.getClass().getName() + ": " + e.getMessage());
        } catch (SQLException e) {
        	System.err.println("2 SQLException");
            succeeded = false;
            throw new LoginException("Erro ao obter conexão: " + e.getClass().getName() + ": " + e.getMessage());
        }
        // valida o usuario
        validaUsuario(conn);
    } finally {
        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
            }
        }
    }
    // acidiona o usuario e roles no mapa de compartilhamento
    sharedState.put("javax.security.auth.principal", user);
    sharedState.put("javax.security.auth.roles", roles);

    return true;
}

public boolean commit() throws LoginException {
	System.err.println("3xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    // adiciona o usuario no principals
    if (user != null && !subject.getPrincipals().contains(user)) {
    	
    	System.err.println("3 user = " + user );
        subject.getPrincipals().add(user);
    }
    // adiciona as roles no principals
    if (roles != null) {
        Iterator it = roles.iterator();
        while (it.hasNext()) {
            Role role = (Role) it.next();
            if (!subject.getPrincipals().contains(role)) {
            	System.err.println("Aqui 3 role = [" + role.getName()+"]" );
            	grupoRole.addMember(role);
            }
        }
        System.err.println("3 adicionando grupoRole" + grupoRole);
        subject.getPrincipals().add(grupoRole);
    }
    
    commitSucceeded = true;
    
    System.err.println("3 commitSucceeded xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    return true;
}

public boolean abort() throws LoginException {
	System.err.println("4xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    if (!succeeded) {
        return false;
    } else if (succeeded && !commitSucceeded) {
        succeeded = false;
    } else {
        succeeded = false;
        logout();
    }

    this.subject = null;
    this.callbackHandler = null;
    this.sharedState = null;
    this.roles = new HashSet();

    return succeeded;
}

public boolean logout() throws LoginException {
	System.err.println("5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    // remove o usuario e as roles do principals
    subject.getPrincipals().removeAll(roles);
    subject.getPrincipals().remove(user);
    return true;
}

/**
 * Valida login e senha no banco
 */
private void validaUsuario(Connection conn) throws LoginException {
	System.err.println("6xxxxxxxxxxxxxxx loginInformado = "+ loginInformado);
    String senhaBanco = null;
    PreparedStatement statement = null;
    ResultSet rs = null;
    try {
        statement = conn.prepareStatement(sqlUser);
        statement.setString(1, loginInformado);
        rs = statement.executeQuery();
        if (rs.next()) {
            senhaBanco = rs.getString(1);
        } else {
            succeeded = false;
            System.err.println("Usuário não localizado.");
            throw new LoginException("Usuário não localizado.");
        }
    } catch (SQLException e) {
        succeeded = false;
        
        System.err.println("Erro ao abrir sessão: "
                + e.getClass().getName() + ": " + e.getMessage());
        throw new LoginException("Erro ao abrir sessão: "
                + e.getClass().getName() + ": " + e.getMessage());
    } finally {
        try {
            if (rs != null)
                rs.close();
            if (statement != null)
                statement.close();
        } catch (Exception e) {

        }
    }

    if (senhaInformado.equals(senhaBanco)) {
        user = new User(loginInformado);
        recuperaRoles(conn);
        user.setRoles(roles);
        return;
    } else {
        throw new LoginException("Senha Inválida.");
    }
}

/**
 * Recupera as roles no banco
 */
public void recuperaRoles(Connection conn) throws LoginException {
	System.err.println("7xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
    PreparedStatement statement = null;
    ResultSet rs = null;
    try {
        statement = conn.prepareStatement(sqlRoles);
        statement.setString(1, loginInformado);
        rs = statement.executeQuery();
        while (rs.next()) {
            roles.add(new Role(rs.getString(1)));
            
            System.err.println("7 rs.getString(1) = ["+rs.getString(1)+"]");
        }
        
        //roles.add(new Role("LOGADO"));
    } catch (SQLException e) {
    	System.err.println("7 SQLException" + "Erro ao recuperar roles: " + e.getClass().getName() + ": " + e.getMessage());
        succeeded = false;
        throw new LoginException("Erro ao recuperar roles: " + e.getClass().getName() + ": " + e.getMessage());
    } finally {
        try {
            if (rs != null)
                rs.close();
            if (statement != null)
                statement.close();
        } catch (Exception e) {

        }
    }
}

/**
 * Login do usuário.
 */
protected String loginInformado;

/**
 * Senha do usuário.
 */
protected String senhaInformado;

/**
 * Obtem o login e senha digitados
 */
protected void getUsernamePassword() throws LoginException {
	System.err.println("8xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
	if (callbackHandler == null) {
		System.err.println("8 callbackHandler == null");
        throw new LoginException("Error: no CallbackHandler available to garner authentication information from the user");
	}
    Callback[] callbacks = new Callback[2];
    callbacks[0] = new NameCallback("Login");
    callbacks[1] = new PasswordCallback("Senha", false);
    try {
        callbackHandler.handle(callbacks);
        loginInformado = ((NameCallback) callbacks[0]).getName();
        char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword();
        senhaInformado = new String(tmpPassword);
        ((PasswordCallback) callbacks[1]).clearPassword();
    } catch (java.io.IOException ioe) {
    	System.err.println("8 ioe");
        throw new LoginException(ioe.toString());
    } catch (UnsupportedCallbackException uce) {
    	System.err.println("8 uce");
        throw new LoginException("Error: " + uce.getCallback().toString() + " not available to garner authentication information from the user");
    }
}

}

M

Cara formata a parada assim…

private GroupRole grupoRole = new GroupRole("abc");

A minha duvida era essa… não sei explicar mas só funciona se colocar

private GroupRole grupoRole = new GroupRole("Roles");
C

Camarada funcionou com o Roles.

Muito obrigado, vou tentar descobrir porque depois coloco no fórum.

Só mais uma dúvida/problema que provavelmente você já deve ter enfrentado.

Agora consegui realizar autenticação e autorização (com a sua ajuda), mas vamos dizer que estou logado com um usuário e quero logar com outro na mesma sessão, ou seja, clico no link da página de login.jsp e entro com outro usuário aparece a seguinte mensagem.

HTTP Status 404 - /teste/j_security_check

Sabe porque? Como contorno isto?

M

Bom … isso eu não sei … e também não sei porque fazer isso… logar 2 usuarios na mesma sessão?

C

Vou tentar melhorar minha pergunta.

Como faço para o container acionar o método logout?

Att,

Anderson de Lima.

M

Bom … eu estrou usando

session.invalidate();

Não fiz os testes ainda com o modulo web, mas está funcionando… o problema é que eu acho que ele está guardando na memória o registro do usuario e da segunda vez eu eu logo ele não busca novamente do banco.

Estou usando a validação em um webservice então como ele é stateless não preciso preocupar com o logout, eu acho.

C

Então amigo,

estou fazendo da mesma forma com session invalidate e ele está também cacheando em algum lugar, porque quando logo a segunda vez ele não consulta de novo no banco.

Além disso, quando executo o invalidate ele não esta chamando o método logout da classe LoginModule.

Queria saber qual evento tenho que gerar para chamar o método logout implementado, pois dai acredito que vai funcionar.

Será que ninguém aqui enfrentou este problema que estamos conversando.

Abraço,

M

É eu reparei nisso. Com webservice ele verifica todas as vezes em que chamo um método, no meu caso, era exatamente o que queria, então não me preocupei com o logout. Pelo que li em um livro PDF - Jaas in Action http://www.jaasbook.com/ ele usa o session invalidate quando utilizado em aplicações web. Só consegui usar o logout quando faço login através do LoginContext, em vez de usar o form.

M

Alguém ai ja usou o LoginContext? Como eu aponto ele para o jboss? Preciso logar uma aplicação swing.

C

Consegui fazer o login utilizando o JASS mas como crio outro projeto e testose o usuário já está logado ou não?

Criado 10 de agosto de 2006
Ultima resposta 25 de fev. de 2013
Respostas 40
Participantes 21