Alguem tem um exemplo pratico de JAAS. Pode ser algo meio rustico, mas ajudaria.
Se alguem poder me ajudar, entao me ajuda pois estou precisando mesmo, ai Moderadores, SiteAdmin, e Geral , se poderem me deem uma força ai …
Olá, lcsoftware,
Como uma implantação JAAS é um pouco dependente da aplicação, vou passando um pouco do que eu já fiz na fase de autenticação:
Primeira fase: criei uma classe derivada de LoginModule
package hipersoft.jaas;
import hipersoft.telensino.*;
import java.util.*;
import java.sql.*;
import java.security.*;
import javax.security.auth.*;
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.login.*;
import javax.security.auth.spi.*;
/**
* Implementa um módulo de autenticação
*
* @author Hipersoft
*/
public class HiperLoginModule implements LoginModule
{
// constantes
private final static int INITIAL_STATE = 0;
private final static int READY = 1;
private final static int PHASE_1_OK = 2;
private final static int PHASE_1_FAILED = 3;
private final static int PHASE_2_OK = 4;
private final static int PHASE_2_FAILED = 5;
private final static int ABORTED = 6;
private final static int CLOSED = 7;
// cache dos parâmetros
private CallbackHandler callbackHandler;
private Subject subject;
private Map sharedState;
private Map options;
// uso interno
private int result = INITIAL_STATE;
private int recurso;
private String conta;
private String senha;
private Principal principal;
private Object credential;
/**
* Construtor padrão (exigido por LoginContext).
*/
public HiperLoginModule()
{
}
/**
* Recebe os parâmetros para a autenticação.
*
* @param subject O Subject que irá ser autenticado
* @param callbackHandler recebe a conta e a senha
* @param sharedState não utilizado por este módulo
* @param options este módulo espera uma par ...
*/
public void initialize(
Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options)
{
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = sharedState;
this.options = options;
result = READY;
}
/**
* Autenticação: fase I
* Faz a autenticação do usuário.
*
* @return true a autenticação foi um sucesso, false a autenticação deve ser ignorada
* @throws LoginException se a autenticação falhou
*/
public boolean login() throws LoginException
{
// callbackHandler é absolutamente necessário neste módulo
//
if(callbackHandler == null)
throw new LoginException("callbackHandler is null");
if(result != READY)
throw new LoginException("illegal state");
//
// monta um array com as propriedades desejadas
//
Callback [] callbacks = new Callback[2];
callbacks[0] = new NameCallback("conta");
callbacks[1] = new PasswordCallback("senha", true);
//
// busca os dados na aplicação
//
Connection con = null;
try
{
callbackHandler.handle(callbacks);
conta = ((NameCallback) callbacks[0]).getName();
senha = new String(((PasswordCallback) callbacks[1]).getPassword());
//
// busca o par conta/senha no backend
//
con = getConnection();
PreparedStatement stmt = con.prepareStatement(
"SELECT recurso FROM Conta WHERE id=? AND senha=?");
stmt.setString(1, conta);
stmt.setString(2, senha);
ResultSet rs1 = stmt.executeQuery();
senha = "***"; // por via das dúvidas!
if(!rs1.next())
{
result = PHASE_1_FAILED;
throw new FailedLoginException("par conta/senha não confere");
}
//
recurso = rs1.getInt(1);
//
stmt.close();
result = PHASE_1_OK;
return true;
}
catch(Exception e)
{
throw new LoginException(e.toString());
}
finally
{
// cala a exceção, pois não se pode fazer nada :(
//
try { con.close(); } catch(Exception e2) {}
}
}
/**
* Autenticação: fase II
* Acrescenta os Principals e Credentials ao Subject
*
* @return true se ok
* @throws LoginException se a fase I havia falhado
*/
public boolean commit() throws LoginException
{
try
{
if(result != PHASE_1_OK)
{
result = PHASE_2_FAILED;
throw new LoginException();
}
//
principal = new ContaPrincipal(conta);
credential = new Integer(recurso);
//
subject.getPrincipals().add(principal);
subject.getPrivateCredentials().add(credential);
result = PHASE_2_OK;
return true;
}
finally
{
conta = null;
recurso = 0;
}
}
/**
* Aborta a autenticação. Limpa os parâmetros.
*/
public boolean abort() throws LoginException
{
try
{
if(result != PHASE_1_OK)
throw new LoginException();
result = ABORTED;
return true;
}
finally
{
conta = null;
recurso = 0;
}
}
/**
* Remove todos os principais e credenciais adicionados ao subject
* por este módulo.
*/
public boolean logout() throws LoginException
{
if(result != PHASE_2_OK)
throw new LoginException();
subject.getPrincipals().remove(principal);
subject.getPrivateCredentials().remove(credential);
if(subject.isReadOnly() && (credential instanceof Destroyable))
throw new LoginException("credential not destroyable");
principal = null;
credential = null;
result = CLOSED;
return true;
}
/*
* Obtém uma conexão com o banco de dados
*/
private Connection getConnection() throws SQLException
{
String url = (String) options.get("url");
String user = (String) options.get("user");
String pass = (String) options.get("pass");
//
//
return DriverManager.getConnection(url, user, pass);
}
}
Segunda fase: Criei um arquivo .jaas.login.config e coloquei no diretório \Windows. O conteúdo do arquivo é o seguinte:
hiperclasse
{
hipersoft.jaas.HiperLoginModule required url=“jdbc:mysql://localhost:3306/hipersoft” user=“hiperclasse” pass=“obeqcucosdbadt”;
};
Terceira fase: Editei o arquivo jre/lib/security/java.security, acrescentando as duas linhas seguintes:
Para o JAAS
login.config.url.1=file:${user.home}/.jaas.login.config
Continuando…
É necessário uma classe callback para trocar informações com o form.
package hipersoft.jaas;
import java.io.IOException;
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;
/**
* Callback handler.
*
* @author Alexandre Furtado Neto
*/
public class HiperHandler implements CallbackHandler
{
private String conta;
private String senha;
/**
* Construtor.
*
* @param conta String com o nome da conta
* @param senha String com a senha
*/
public HiperHandler(String conta, String senha)
{
this.conta = conta;
this.senha = senha;
}
/**
* Invoke an array of Callbacks.
*
* @param callbacks array com as funções callback
*/
public void handle(Callback[] callbacks)
throws IOException, UnsupportedCallbackException
{
for(int i = 0; i < callbacks.length; i++)
{
if(callbacks[i] instanceof NameCallback)
((NameCallback) callbacks[i]).setName(conta);
else if(callbacks[i] instanceof PasswordCallback)
((PasswordCallback) callbacks[i]).setPassword(senha.toCharArray());
else
throw new UnsupportedCallbackException (callbacks[i], "Unrecognized Callback");
}
}
}
Continuando…
O código de ligação deve ser colocado na servlet controladora. É importante ressaltar que este código é muito dependente da aplicação.
/*
* Tenta re-login de um usuário.
*/
public void login() throws LoginException
{
// checa se o usuário já está autenticado
//
subject = (Subject) session.getAttribute("subject");
if(subject == null && autologin)
{
// tenta obter a conta do usuário a partir de um cookie deixado previamente
//
Cookie [] cookies = req.getCookies();
if(cookies != null)
{
for(int i = 0; i < cookies.length; i++)
{
Cookie cookie = cookies[i];
String name = cookie.getName();
if(name.equals("conta"))
{
String conta = cookie.getValue();
//
// recupera a senha do banco de dados
//
try
{
Connection con = portal.dbpool.getConnection();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(
"SELECT senha FROM Conta WHERE id='" + conta + "'");
if(!rs.next())
throw new LoginException("conta '" + conta + "' não encontrada");
String senha = rs.getString(1);
//
// força o login do usuário
//
login(conta, senha);
senha = null; // por via das dúvidas...
//
// diminui os privilégios, pois é um login sem senha
//
Set credentials = subject.getPrivateCredentials();
credentials.clear();
credentials.add(new Integer(Acesso.FORUM));
//
rs.close();
stmt.close();
//
// tenta abrir o bean de usuário do fórum
//
UsuarioBean usuariobean = new UsuarioBean(conta);
session.setAttribute("usuariobean", usuariobean);
try
{
usuariobean.load(con);
}
catch(SQLException e)
{
// ignora
}
//
con.close();
}
catch(Exception e)
{
throw new LoginException(e.toString());
}
}
}
}
}
}
/*
* Força o login de um usuário.
*/
public void login(String conta, String senha) throws LoginException
{
CallbackHandler callbackhandler = new HiperHandler(conta, senha);
LoginContext logincontext = null;
//
// cria um contexto para autenticação TODO: passar o nome do login module
//
logincontext = new LoginContext("hiperclasse", callbackhandler);
//
// authenticate the Subject
//
logincontext.login();
subject = logincontext.getSubject();
//
// salva na sessão (será usado para autenticação doravante até logout)
//
session.setAttribute("subject", subject);
//
// lança um cookie para re-login
//
if(req.isRequestedSessionIdFromCookie())
{
// cria e envia um cookie com a conta
//
Cookie cookie = new Cookie("conta", conta);
cookie.setMaxAge(60 * 60 * 24 * 30 * 6); // 6 meses
res.addCookie(cookie);
}
//
// atualiza o controle de acesso da conta
//
try
{
Connection con = portal.dbpool.getConnection();
Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(
"SELECT acesso,contador FROM Conta WHERE id='" + conta + "'");
if(rs.next())
{
session.setAttribute("conta.acesso", rs.getTimestamp(1));
session.setAttribute("conta.contador", rs.getString(2));
rs.close();
//
// avança o contador e atualiza o acesso (indiretamente)
//
stmt.executeUpdate("UPDATE Conta SET contador=contador+1");
}
stmt.close();
con.close();
//
getConta();
}
catch(Exception e)
{
throw new LoginException(e.toString());
}
}
Continuando…
Ia esquecendo do Principal (com trocadilho, por favor):
package hipersoft.jaas;
import java.security.Principal;
/**
* Esta classe implementa a interface <code>Principal</code> e representa
* uma conta de usuário.
*
* @author Alexandre Furtado Neto
*/
public class ContaPrincipal implements Principal, java.io.Serializable
{
/**
* @serial
*/
private String conta;
/**
* Construtor
*
* @param conta the Conta username for this user.
* @exception NullPointerException if the <code>conta</code>
* is <code>null</code>.
*/
public ContaPrincipal(String conta)
{
if(conta == null)
throw new NullPointerException("illegal null input");
this.conta = conta;
}
/**
* Return the Conta username for this <code>ContaPrincipal</code>.
*
* <p>
*
* @return the Conta username for this <code>ContaPrincipal</code>
*/
public String getName()
{
return conta;
}
/**
* Return a string representation of this <code>ContaPrincipal</code>.
*
* <p>
*
* @return a string representation of this <code>ContaPrincipal</code>.
*/
public String toString()
{
return("ContaPrincipal: " + conta);
}
/**
* Compares the specified Object with this <code>ContaPrincipal</code>
* for equality. Returns true if the given object is also a
* <code>ContaPrincipal</code> and the two ContaPrincipals
* have the same username.
*
* <p>
*
* @param o Object to be compared for equality with this
* <code>ContaPrincipal</code>.
*
* @return true if the specified Object is equal equal to this
* <code>ContaPrincipal</code>.
*/
public boolean equals(Object o)
{
if(o == null)
return false;
if(this == o)
return true;
if(!(o instanceof ContaPrincipal))
return false;
ContaPrincipal that = (ContaPrincipal) o;
if(this.getName().equals(that.getName()))
return true;
return false;
}
/**
* Return a hash code for this <code>ContaPrincipal</code>.
* <p>
* @return a hash code for this <code>ContaPrincipal</code>.
*/
public int hashCode()
{
return conta.hashCode();
}
}
Valeu hipersoft se precisar de algo ai mano pode falar que te ajudo na hora, valeu por COMPARTILHAR SEU CONHECIMENTO, não são todos que possuem essa Capacidade. Se precisar to ai mano.
Para quem está brigando com a fase de autorização do JAAS, e está querendo inserir permissões dinamicamente, uma possibilidade é editar o arquivo seguinte que, ao reler o arquivo de política, poderia introduzir as regras vindas, digamos, do banco de dados.
http://mail.gnu.org/archive/html/classpath/2003-12/txt00008.txt
A propósito…
Se alguém conseguir fazer isso com sucesso, por favor, poste o código aqui no fórum.
Olá,
Hipersoft, ficou bacana o exemplo. Você poderia fazer um tutorial em cima destes códigos para colocarmos aqui no PJ. O que acha?
Deve ser fácil de fazer já que está praticamente tudo pronto…
Olá, Franklin
Assim que eu amadurecer um pouco mais a idéia, eu disponibilizo o tutorial no fórum.
T+
Existe um tutorial legal em:
http://java.sun.com/j2se/1.4.2/docs/guide/security/jaas/JAASRefGuide.html#Introduction
Tudo bem?
E como ficaria esse teu exemplo rodando no JBOSS?
Abração,
Mick.
Onde eu devo criar o seguinte arquivo: jaas.login.config?
no meu projeto, diretótio, etc. :?: :?: :?: :?:
E como faço para utiliza-lo?
Que lugar deste arquivo java.securitydevo editar :?: :?: :?: