1. java
  2. android
  3. c#
  4. .net
  5. javascript
  6. php
  7. jquery
  8. html
  9. sql

Logout SSL (JBoss AS 7.1, JDK 1.6 e JSF 2)

Bom dia.

Estou com um problema no momento em que tento realizar logout no sistema autenticado através de um Certificado Digital.

Para melhor descrever o problema é o seguinte:

O navegador apresentada a caixa de seleção de certificados para autenticação, selecionando e fornecendo o PIN para o certificado selecionado o sistema realiza login normalmente. O problema se encontra no momento que o usuário aciona o botão de logout, ele invalida a sessão e redireciona para a tela de login novamente. Contudo no momento em que o usuário clica no botão que redireciona para uma área restrita o navegador deveria apresentar novamente a caixa de seleção de certificados, mas o mesmo passa direto, utilizando as informações do certificado selecionado no login anterior.

Se pararmos o servidor ou fechar e abrir o navegador ele irá solicitar novamente a escolha do certificado.

As configurações são as seguintes:

standalone.xml:

 <subsystem xmlns="urn:jboss:domain:web:1.1" default-virtual-server="default-host" native="false">
        <connector name="http" protocol="HTTP/1.1" scheme="http" socket-binding="http" redirect-port="8443"/>
        <connector name="https" protocol="HTTP/1.1" scheme="https" socket-binding="https" secure="true">
            <ssl key-alias="localhost" verify-client="true"/>
        </connector>
        <virtual-server name="default-host" enable-welcome-root="true">
            <alias name="localhost"/>
            <alias name="example.com"/>
        </virtual-server>
    </subsystem>

web.xml:

    <filter>
        <filter-name>Authentication X509Certificate Filter</filter-name>
        <filter-class>br.gov.sp.sefin.desif.security.servlet.AuthX509CertificateFilter</filter-class>
    </filter>

    <filter-mapping>
        <filter-name>Authentication X509Certificate Filter</filter-name>
        <url-pattern>/pages/*</url-pattern>
    </filter-mapping>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>pages/*</web-resource-name>
            <url-pattern>/pages/*</url-pattern>
            <http-method>GET</http-method>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

    <login-config>
        <auth-method>CLIENT-CERT</auth-method>
    </login-config>

Filtro Altenticação AuthX509CertificateFilter :

public class AuthX509CertificateFilter implements Filter {

    private static final String MS_005 = "MS_005";
    private static final String URI_DEFINIR_IF = "/internet/pages/home.xhtml";

    private Principal authenticatedUser;

    @Inject
    private RepresentanteBO representanteBO;

    @Inject
    private InstituicaoFinanceiraBO instituicaoFinanceiraBO;

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        Object attrSessionValid = req.getSession().getAttribute("sessionValid");
        Object attrSessionAuthenticated = req.getSession().getAttribute("authenticated");
        Object attrSessionInstituicaoFinanceira = req.getSession().getAttribute("instituicaoFinanceiraInternet");
        Boolean sessionValid = (Boolean) (attrSessionValid != null ? attrSessionValid : Boolean.FALSE);
        Boolean sessionAuthenticated = (Boolean) (attrSessionAuthenticated != null ? attrSessionAuthenticated : Boolean.FALSE);
        if(!sessionValid || (URI_DEFINIR_IF.equals(req.getRequestURI()) && attrSessionInstituicaoFinanceira == null)) {
            X509Certificate certs[] = (X509Certificate[] )req.getAttribute("javax.servlet.request.X509Certificate");
            if(certs != null) {
                X509Certificate t = (X509Certificate) certs[0];
                Principal subjectDN = t.getSubjectDN();
                authenticatedUser = subjectDN;
                sessionAuthenticated = validarAutenticacao(subjectDN, req, resp);                        
                chain.doFilter(new HttpServletRequestWrapper(req) {
                    @Override
                    public Principal getUserPrincipal() {
                        return authenticatedUser;
                    }
                }, response);
            }
        } else {
            Principal userPrincipal = req.getUserPrincipal();
            if(userPrincipal != null) {
                sessionAuthenticated = validarAutenticacao(userPrincipal, req, resp);
            }
            chain.doFilter(new HttpServletRequestWrapper(req) {
                @Override
                public Principal getUserPrincipal() {
                    return authenticatedUser;
                }
            }, response);
        }

        if(!resp.isCommitted() && !sessionAuthenticated) {
            Object attribute = req.getSession().getAttribute("cpfCnpj");
            if(attribute != null)
                req.getSession().setAttribute(MS_005, MessagePtBrUtil.recupera(MS_005, UtilFormatter.formatarCPF((String) attribute)));
            RequestDispatcher dispatcher = req.getRequestDispatcher("../login.xhtml");
            dispatcher.forward(req, resp);
        }
    }


    public void atualizarDadosDeSessao(HttpServletRequest req, Boolean sessionValid, Boolean sessionAuthenticated) {
        req.getSession().setAttribute("sessionValid", sessionValid);
        req.getSession().setAttribute("authenticated", sessionAuthenticated);
    }

    public Boolean validarAutenticacao(Principal userPrincipal, HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Boolean sessionValid = Boolean.TRUE;
        Boolean sessionAuthenticated = Boolean.TRUE;
        String[] cn = userPrincipal.getName().split(",");
        String cpfCnpj = cn[0].split(":")[1];
        req.getSession().setAttribute("cpfCnpj", cpfCnpj);
        BigInteger raizCnpj = new BigInteger(cpfCnpj.substring(0, 8));
        if(cpfCnpj.length() == 14 && instituicaoFinanceiraBO.verificarInstituicaoFinanceiraRaizCnpj(raizCnpj)) {
            RequestDispatcher dispatcher = req.getRequestDispatcher("../pages/home.xhtml");
            dispatcher.forward(req, resp);
        } else {
            BigInteger cpf = new BigInteger(cpfCnpj);
            if(representanteBO.verificarRepresentanteInstituicaoFinanceira(cpf)) {
                RequestDispatcher dispatcher = req.getRequestDispatcher("../pages/autenticarusuario/definirInstituicaoFinanceira.xhtml?cpf="+cpf);
                dispatcher.forward(req, resp);
            } else { // não tem instituição financeira vinculada ao CPF
                sessionValid = Boolean.FALSE; sessionAuthenticated = Boolean.FALSE;
            }
        }
        atualizarDadosDeSessao(req, sessionValid, sessionValid);
        return sessionValid && sessionAuthenticated;
    }

    @Override
    public void destroy() {

    }
}

Método de Logout:

public void sair() {
    ExternalContext context = FacesContext.getCurrentInstance().getExternalContext();
    this.inserirLogAuditoriaLogout();
    context.invalidateSession();

    HttpServletRequest request = (HttpServletRequest) context.getRequest();

    request.getSession().setAttribute("sessionValid", Boolean.FALSE);
    request.getSession().setAttribute("authenticated", Boolean.FALSE);

    try {
        request.logout();
        context.redirect("/internet/login.xhtml");
    } catch (IOException e) {
        new IOException();
    } catch (ServletException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

Já tentei utilizar algumas soluções em javascript para realizar a limpeza do dados de autenticação por certificado armazenados no navegador. Exemplo:

window.crypto.logout();

document.execCommand("ClearAuthenticationCache");



function logOut()
{
    var xmlHttp = new XMLHttpRequest();

    xmlHttp.timeout = 2000; // 2 seconds

    xmlHttp.onreadystatechange = function ()
    {
        if (xmlHttp.readyState == 4)
        {
            console.log("status: "+xmlHttp.status);
            console.log("response: '"+xmlHttp.responseText+"'");
        }
    };
    xmlHttp.open("GET", "/internet/login.xhtml", true);
    xmlHttp.send();
}

Mas não funcionaram.

Por favor, se alguém já passou por isso e obteve sucesso em resolve-lo apresente sua solução.

Espero que eu possa ter sido claro na descrição do problema. Estou a disposição para melhor descreve-lo.

Desde já agradeço muito sua atenção.

  • Ninguém? Realmente estou precisando disso. ;(

    DDionizio   07 de jan de 2015
  • AMIGO, me ajuda '-', estou precisando realizar um login com certificado digital, mas achei tanta documentação confusa, você tem como me ajudar ? Na minha aplicação por exemplo eu não consigo pegar isso javax.servlet.request.X509Certificate, preciso adicionar algum jar ?

    rof20004   16 de mai de 2016
  1. Você vai ver essas setas em qualquer página de pergunta. Com elas, você pode dizer se uma pergunta ou uma resposta foram relevantes ou não.
  2. Edite sua pergunta ou resposta caso queira alterar ou adicionar detalhes.
  3. Caso haja alguma dúvida sobre a pergunta, adicione um comentário. O espaço de respostas deve ser utilizado apenas para responder a pergunta.
  4. Se o autor da pergunta marcar uma resposta como solucionada, esta marca aparecerá.
  5. Clique aqui para mais detalhes sobre o funcionamento do GUJ!

1 resposta

Não é a resposta que estava procurando? Procure outras perguntas com as tags ssl jboss jsf ou faça a sua própria pergunta.