Custom JAAS LoginModule não esta setando Group no Principal

1 resposta
R

Bom dia a todos! agradeceria muito uma força com um problema que estou tendo.

Tenho un projeto rodando no Wildfly 8, como sistema de login, estou usando JAAS com a implementação padrão. Devido a uma mudança no controle de login, me vi obrigado a customizar o JAAS através da sua interface LoginModule.
A redireção para a tela de login funciona de maravilha, assim como a redireção para a tela de erro quando o usuário não consegue logar. O único problema é quando o usuário informa login e senha validos, o usuário é setado na sessão mas o rol não esta sendo setado, sendo que o JAAS não permite o acesso ás paginas protegidas pelo JAAS.

Uma vez que o usuario consegue logar, faco as seguintes verificações:

User user = (User) request.getUserPrincipal(); //retorna o usuário certo
        if(user!=null){

            System.out.println(user.getName());
            Set roles = user.getRoles();
            for (Object object : roles) {
                Role rol = (Role) object;    
                System.out.println(rol.getName()); //Retorna o rol certo (admin)
            }
        }
        System.out.println(request.isUserInRole("admin")); // retorna false

Obrigado pela ajuda!!!

segue o código:

Classe User :

import java.io.Serializable;
import java.security.Principal;
import java.util.Set;

public class User implements Principal,Serializable{
    
    private String name;
    private Set roles;
    public User(String name){
        System.out.println("setando user "+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;
    }

}

Classe Roles:

public class Role implements Principal,Serializable{

    private String name;
    public Role(String name){
        System.out.println("setando role "+name);
        this.name = name;
    }
    public String getName() {
        return name;
    }
    
}

Classe LoginModule:

import java.nio.Buffer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
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 javax.sql.DataSource;

public class LoginModule 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;
    /*
     * Login do usuário.
     */
    protected String loginInformado;
    /*
     * Senha do usuário.
     */
    protected String senhaInformado;

    /*
    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 (arquivo de configuração do JAAS). O mais importante destes parametros para nós será o options,
    pois nele receberemos os parametros de sql e datasource.
     * */
    @Override
    public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState,
            Map<String, ?> options) {
        
        this.subject = subject;
        this.callbackHandler = callbackHandler;
        this.sharedState = sharedState;
        dataSourceName = "java:jboss/datasources/CacDb";
        sqlUser = "SELECT senha as 'password' FROM SXML_USUARIO WHERE email = ?";
        sqlRoles = "SELECT grupo , 'Roles' FROM SXML_USUARIO WHERE email = ?";
        
    }

    /*O método login() é invocado quando é enviado os dados (login e senha) de autenticação.*/
    @Override
    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) initContext.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());
            }catch (Exception e) {
                e.printStackTrace();
            }
            // valida o usuario
            validaUsuario(conn);
        } finally {
            if (conn != null) {
                try {
                    conn.close();
                } catch (SQLException e) {
                }
            }
        }
        // acidiona o usuario e roles no mapa de compartilhamento
        
        for (Object object : Roles) {
            Role rol = (Role) object;
            System.out.println(rol.getName());
        }
        
        sharedState.put("javax.security.auth.principal", user);
        sharedState.put("javax.security.auth.roles", Roles);
        return true;
    }
    
    /*O método commit() é invocado quando o login() obtém sucesso.*/
    @Override
    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);
                }
            }
        }
        System.out.println(subject.toString());
        commitSucceeded = true;
        return true;
    }

    /*O método abort() é invocado quando o login() não obtém sucesso.*/
    @Override
    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;
    }

    /*O método logout() é invocado quando o usuário desloga da aplicação.*/
    @Override
    public boolean logout() throws LoginException {
        // remove o usuario e as roles do principals
        subject.getPrincipals().removeAll(Roles);
        subject.getPrincipals().remove(user);
        return true;
    }
    
    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 (stringToMD5(senhaInformado).equals(senhaBanco)) {
            user = new User(loginInformado);
            recuperaRoles(conn);
            user.setRoles(Roles);
            return;
        } else {
            throw new LoginException("Senha Inválida.");
        }
        
    }

    private String stringToMD5(String senhaInformada) {
        String MD5 = null;
        
        try {
            MessageDigest encripter = MessageDigest.getInstance("MD5");
        
            encripter.update(senhaInformada.getBytes());
            byte[] senhaEncriptada = encripter.digest();
            StringBuffer buffer = new StringBuffer();
            for (byte b : senhaEncriptada) {
                buffer.append(String.format("%02x", b & 0xff));
            }
            MD5 = buffer.toString();
        } catch (NoSuchAlgorithmException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }catch (Exception e) {
            e.printStackTrace();
        }
        
        return MD5;
    }

    private 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()) {
                System.out.println(rs.getString(1));
                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) {
            }
        }
        
    }

    private 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");
        }
    }

    

}

web.xml:

<!-- Somente admin -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Users and admins</web-resource-name>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>
  
      <!-- Somente logados -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Users and admins</web-resource-name>
            <url-pattern>/private/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
            <role-name>user</role-name>
        </auth-constraint>
    </security-constraint>
 
    <!-- Validation By Form -->
    <login-config>
        <auth-method>FORM</auth-method>
        <form-login-config>
            <form-login-page>/public/login/</form-login-page>
            <form-error-page>/public/login/?error=true</form-error-page>
        </form-login-config>
    </login-config>
 
    <!-- Allowed Roles -->
    <security-role>
        <role-name>admin</role-name>
    </security-role>
    <security-role>
        <role-name>user</role-name>
    </security-role>

jboss-web:

<jboss-web>
    <security-domain>tiss-domain</security-domain>
    <context-root>/tiss</context-root>
</jboss-web>

standalone.xml:

<security-domain name="tiss-domain" cache-type="default">
        <authentication>
              <login-module code="br.org.cac.tiss.login.LoginModule" flag="required">
              </login-module>
         </authentication>
</security-domain>

1 Resposta

F

Cara , estou com o mesmo problema que o seu , voce conseguiu resolver isto ?

Vlw …

Criado 7 de março de 2016
Ultima resposta 30 de mai. de 2016
Respostas 1
Participantes 2