Archive for June 7th, 2008

Em um dos clientes que eu estamos atendendo na empresa, um dos requisitos é autenticar no RACF, uma espécie de LDAP para o Mainframe. Nosso cliente, disponibilizou um WS que faz este trabalho “sujo”. Nos resta então criar um LoginModule que suporte esta nova funcionalidade.

Quando você proteger Aplicações em Java é importante saber onde você pode se conectar, o JBoss oferece por padrão alguns LoginModules, entre eles:

-LoginModule baseado em arquivos properties
-LoginModule baseado em Banco de Dados
-LoginModule para LDAP

Em nossa solução, estaremos promovendo mais um LoginModule. O primeiro passo é alterar o login-config.xml dentro de /default/conf, no caso adicionamos mais um LoginModule, como a seguir:
Screenshot-*login-config.xml (-opt-java-jboss-as-jboss-4.2.2.GA-server-dev-conf) - gedit.png

Adicionamos até uma propriedade, que é o WSDL do Serviço, que pode variar dependendo do caso, e ai a configuração poderá ser feita no LoginModule, sem a necessidade de recompilação.

Estamos dizendo acima que a classe org.jboss.security.auth.api.JBossLoginModuleWS é a implementação deste mecanismo de Login. Veja o código-fonte de exemplo:

[java]

package org.jboss.security.auth.api;
import java.security.acl.Group;
import java.util.Map;
import javax.security.auth.Subject;
import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import org.jboss.security.SimpleGroup;
import org.jboss.security.SimplePrincipal;
import org.jboss.security.auth.spi.UsernamePasswordLoginModule;
import org.jboss.security.auth.api.ws.client.*;
import org.jboss.security.auth.ws.AutenticateProxy;
/**
*
* @author Edgar Silva
*/
public class JBossLoginModuleWS extends UsernamePasswordLoginModule {
/**
* WSDL address
*/
private String wsdl;
protected org.jboss.security.auth.ws.Principal p;
public JBossLoginModuleWS() {
super();
}
@Override
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
super.initialize(subject, callbackHandler, sharedState, options);
log.info("WebServices Login Module : initialize");
}
@Override
protected String getUsersPassword() throws LoginException {
return "";
}
@Override
protected boolean validatePassword(String inputPassword, String expectedPassword) {
boolean isValid = false;
if (inputPassword != null) {
try {
log.info("Connecting via WS ..............");
String username = getUsername();
log.info("UserName: " + getUsername());
log.info("Password: "+ inputPassword);
p = new AutenticateProxy().autentica(username, inputPassword);
log.info("Connected as: " + p.getUsuario());
isValid = (p != null);
} catch (Throwable e) {
e.printStackTrace();
super.setValidateError(e);
}
}
return isValid;
}
@Override
protected Group[] getRoleSets() throws LoginException {
SimpleGroup userRoles = new SimpleGroup("Roles");
userRoles.addMember(new SimplePrincipal(p.getGrupo()));
Group[] roleSets = {userRoles};
return roleSets;
}
public String getWsdl() {
return wsdl;
}
public void setWsdl(String wsdl) {
this.wsdl = wsdl;
}
}

[/java]

Agora, a qualquer momento que você proteger uma Aplicação Web, ou quiser utilizar o Servidor de Aplicações para fazer isto, você deverá configurar o jboss-web.xml para apontar para o LoginModule que voce configurou no login-config.xml, veja o exemplo a seguir:
jboss-web.xml

Além desta configuração, você deverá proteger as páginas de uma Aplicação Web, por exemplo, sendo assim, você irá configurar o web.xml da sua aplicações para pedir o “Realm”(LoginModule) que vc configurou com o nome WSLoginModule, em nosso caso vamos liberar apenas o acesso as páginas .jsp caso o Login seja efetivado no WebServices de autenticação. Veja o web.xml:

web.xml

Esta é mais uma dica, que sei que posso precisar um dia novamente!

[]s
E