2 duvidas com JAAS

Olá!

Tenho q fazer uma alteração em um sistema onde o jaas já está implementado…
Ele chama uma procedure oracle para fazer a validação de senha!

Tenho 2 dúvidas:

:?: Uma é que vai ser incluso 2 parametros na proc onde tenho q passar o IP e Host para gravar log (procedure irá fazer isto - varios sistemas chamam esta mesma procedure)!
Voces tem alguma idéia de como fazer isto?
Como solucao porca mas que sei q funciona e pensei em colocar no jsp o j_username como hidden e antes de submeter via javascript eu conteno o ip e host no campo para trafegar para o Login module (o usuário para o jaas estaria algo como flasoft;meuHost;10.1.1.10), lá eu dou um split e chamo a proc normalmente! (porco mas funciona, vcs tem outra idéia?)

:?: Quando o login falha é lancado uma exceção no login module só que “alguma coisa” engole esta exceção e meu Handler exception nao pega ela! Tem como eu manipular as exceções lancadas no login module na jsp ( tipo eu queria na jsp algo como <%= exception.getMensage() %> )

Desde já obrigado pessoal!
Eu tenho q fazer isto até quarta… se eu não conseguir to ferrado! To mais preocupado com a segundo item, pois apesar da primeira solucao ser feia pelo menos é uma solucao! :roll:

Como você precisa de tudo isso no JAAS, acredito que implementar um login module seja o mais aconselhado. Há um exemplo aqui mesmo no guj que pode te ajudar.

Como você tem apenas dois dias acho que sua gambiarra pode funcionar sim. Como você mesmo disse não é algo muito elegante, mas dentro do prazo que você tem é o mais indicado.

Você consegue personalizar os campos do JAAS, porém você precisa escrever algumas coisinhas um pouco complicadas. Aqui há dois links da documentação oficial do JAAS, vai te ajudar.

http://java.sun.com/javase/6/docs/technotes/guides/security/jaas/JAASLMDevGuide.html
http://java.sun.com/javase/6/docs/technotes/guides/security/jaas/JAASRefGuide.html

Em um projeto que estou desenvolvendo possui autenticação via certificado digital via JAAS. Como no JAAS ele apenas valida o certificado e autoriza ou não, tenho um componente do vraptor que faz um pós login, e você pode aproveitar a idéia. O que faço nele basicamente é após o login inicializar esse componente. Nele através do HttpServletRequest eu pego o Principal, IP e mais algumas informaçoes do usuário e adiciono na session, gravando os dados de username, ip e data na base de dados. Ou seja, no contexto do JAAS possuo todos os dados necessários como o objeto Principal e as roles do usuário, assim o módulo EJB pode controlar o acesso normalmente. Os dados estendidos do usuário como nome, email, ultimo login… ficam nesse objeto de sessão.

O que você acha? Isso te ajuda?

Abraços

Pode me dar um norte de como separar os campos, alguma dica para eu comecar a pesquisar?

E quanto a mensagem na pagina de login invalido tem alguma idéia?

No web.xml eu tenho:

<!-- Define o modulo de logon --> <login-config> <auth-method>FORM</auth-method> <realm-name>my-apps</realm-name> <form-login-config> <form-login-page>/logon.do</form-login-page> <form-error-page>/acessonaoautorizado.do</form-error-page> </form-login-config> </login-config>

Minha personalização do loginModule (DatabaseLoginModule só faz a conn com o bd):

[code]public class MyAuthLoginModule extends DatabaseLoginModule {

/** This constant represents the service Log instance */
private static final Log log = LogFactory.getLog(this.getClass().class);
/** This constant represents the batch command to execute to verify the authentication */
private static final String PRINCIPALS_BATCH_COMMAND = "{call PKG_SENHAS.VALIDA_SENHA(?,?,?,?,?,?)}";
/** This constant represents the password expired key to set in the principal properties */
private static final String PASSWORD_EXPIRED = "passwordExpired";
/** This constant represents the key of principal object to configure to work in JBOSS AS */
private static final String CALLER_PRINCIPAL = "CallerPrincipal";
/** This constant represents the property configuration key to configure the datasources to authenticate */
private static final String DATASOURCES = "dataSources";
/** This attribute represents the behavior for expired passwords */
private boolean passwordExpired;


private String[] getDataSourcesList() {
	String dataSources = (String) options.get(DATASOURCES);
	String[] items = dataSources.split(",");
	String[] result = new String[0];
	if (items != null) {
		result = new String[items.length];
		for (int i = 0; i < items.length; i++)
			result[i] = items[i].trim();
	}
	return result;
}

@Override
public boolean login() throws LoginException {
	// The result method flag
	boolean result = false;

	// Retrieving the username and password inputed by user
	String username = retrieveUsername();
	String inputPassword = retrieveInputPassword();
	
	String[] dataSources = getDataSourcesList();
	
	for (int i = 0; i < dataSources.length; i++) {
		
		Transaction transaction = null;
		Connection connection = null;
		CallableStatement cstmt = null;
		
		try {
			// Suspend all current transactions in current datasource
			transaction = suspendTransaction();
			// Retrieve the configured datasource
			InitialContext context = new InitialContext();
			DataSource dataSource = (DataSource) context.lookup(dataSources[i]);
			// Retrieving a new connection
			connection = dataSource.getConnection();
			// Preparing to execute the PL-SQL
			cstmt = connection.prepareCall(PRINCIPALS_BATCH_COMMAND);
			// Setting parameters to execute the PL-SQL
			cstmt.setObject(1, username);
			cstmt.setObject(2, inputPassword);			
			cstmt.setNull(3, Types.FLOAT);
			cstmt.registerOutParameter(3, Types.FLOAT);
			cstmt.setNull(4, Types.FLOAT);
			cstmt.registerOutParameter(4, Types.FLOAT);
			cstmt.setNull(5, Types.INTEGER);
			cstmt.registerOutParameter(5, Types.INTEGER);
			cstmt.setNull(6, Types.VARCHAR);
			cstmt.registerOutParameter(6, Types.VARCHAR);
			// Executing the PL-SQL
			cstmt.execute();
			// Retrieving the expired password flag (1 = expired | 0 = not expired)
			Float expired = cstmt.getFloat(4);
			// Retrieving the valid login flag (1 = invalid login | 0 = valid login)
			Float validLogin = cstmt.getFloat(3);
			// Retrieving the error code to be verifyied
			Float errorCode = cstmt.getFloat(5);
			
			if (errorCode == 10 || errorCode == 8 || errorCode == 7) { 
				throw new FailedLoginException(cstmt.getString(6));
			} else if (errorCode == 0) {
				if (expired == 1 && validLogin == 0)
					passwordExpired = true;
				else if (expired == 1 && validLogin == 1)
					throw new FailedLoginException(cstmt.getString(6));
				else if (expired == 0 && validLogin == 1)
					throw new FailedLoginException(cstmt.getString(6));
			} else if (errorCode == 12) {
				// If the error code is equals of 10 or 12, sets the expired password to true to be changed in the change password screen
				passwordExpired = true;
			} else {
				throw new FailedLoginException(cstmt.getString(6));
			}
			
			log.debug("Returning the success in processing of login() method for requested user ['" + username + 
					"'] through datasource ['" + dataSources[i] + "']");
			// Return the success of the login process
			result = true;				
			sharedState.put(DS_JNDI_NAME, dataSources[i]);				
			break;
			
		} catch (Exception ex) {
			if (ex instanceof LoginException) {
				throw (LoginException) ex;
				
			} else if (ex instanceof FailedLoginException) {
				log.debug("Failed to validate the requested user ['" + username + "'] through datasource ['" + 
						dataSources[i] + "']", ex);
				throw (FailedLoginException) ex;
				
			} else if (ex instanceof SQLException || ex instanceof NamingException) {
				log.warn("Problem to connect in the datasource ['" + dataSources[i] + "'] requested by user ['" + username + "']", ex);
				
			} else {
				log.error("Error occurried in processing of login() method requested by user ['" +
						username + "'] through datasource ['" + dataSources[i] + "']", ex);
				throw new LoginException(ex.getMessage());
			}
			
		} finally {
			if (cstmt != null)
				try {
					cstmt.close();
				} catch (SQLException ex) {
					log.warn("Error occurried when close the CallableStatement JDBC", ex);
				}
			if (connection != null)
				try {
					connection.close();
				} catch (SQLException ex) {
					log.warn("Error occurried when close the Connection JDBC", ex);
				}
			if (transaction != null)
				// Resuming the all stopped transactions
				resumeTransaction(transaction);
		}
	}		
	return result;
}

@Override
public boolean commit() throws LoginException {
	boolean result = super.commit();
	
	String username = retrieveUsername();
	
	BasePrincipal basePrincipal = null;
	
	Iterator<Principal> iterator = subject.getPrincipals().iterator();
	while (iterator.hasNext()) {
		Principal principal = iterator.next();
		if (username.equalsIgnoreCase(principal.getName())) {
			basePrincipal = (BasePrincipal) principal;
			break;
		}
	}		
	
	if (basePrincipal != null) {
		basePrincipal.getProperties().put(PASSWORD_EXPIRED, passwordExpired);
		BaseGroup callerPrincipal = new BaseGroup(CALLER_PRINCIPAL);
		callerPrincipal.addMember(basePrincipal);
		subject.getPrincipals().add(callerPrincipal);
	}
	
	if (log.isDebugEnabled())
		log.debug("Commiting the user authentication information for requested user ['" + username + "']");
	
	return result;
}

}
[/code]

Estas actions configuradas referentes ao login:

[code]




<!-- Carrega Menu Action -->
<action path="/login" 
		parameter="acao"
		type="br.com.web.struts.action.LoginAction">
		
	<forward name="success_processLogin" 	path="global.base"/>
	<forward name="error_processLogin"   	path="global.acessonaoautorizado"/>
	<forward name="success_passwordExpired" path="/changePassword.do?acao=prepareInsert"/>
</action>

<!-- Logout Action -->
<action path="/logout" 
		parameter="acao"
		type="br.com.web.struts.action.SimpleCadAction">
	<forward name="success_welcome" path="/index.do" redirect="true"/>
</action>    

[/code]

A jsp de senha invalida!

[code]
<%@ taglib uri="/tags/struts-bean" prefix=“bean” %>
<%@ taglib uri="/tags/c" prefix=“c” %>







[/code]

E não sei bem como um metodo processLogin de uma action loginAction é chamado quando o método login da MyAuthLoginModule retorna true… aqui é possivel colocar coisas na sessão… mas se uma exceção é lancada na MyAuthLoginModule a action não é chamada e com isto não consigo colocar mais nada na sessão…

Alguém conhece?

Flasoft, não sei se entendi bem tua dúvida. Creio que você entendeu errado o conceito do jaas.

Jaas não fica na http-session. QUando você, via web.xml, indica qual realm será usado para autenticação ele irá fazer o login nesse realm (que pode ser um login-module personalizado como o seu) e vai colocar isso no contexto do jaas. Nada de sessão é envolvida, já que o jaas é portável entre desktop e web.

Se você estiver na página web e precisa saber o usuário basta fazer HttpServletRequest.getUserPrincipal(). Caso você estiver no EJB ou algum outro local dá para buscar pelo Subject, porém não lembro de cabeça.

Mas enfim, como já passou algum tempo, você resolveu o problema?

Abraços

Ainda não funcionou, me deram + prazo…
O que ocorre é que dentro do Metodo login() é lançado algumas exceções, na jsp de senha inválida preciso exibir na pagina exception.getMensage()