Web Service Client com acesso HTTPS

33 respostas
lblanco

Boa tarde,

Usando o netbeans, criei um projeto baseando-se em uma URL que aponta para um WSDL. Por se tratar de uma aplicação segura, alguns certificados foram mostrados na tela do NetBeans durante a criação e eu os aceitei, concluí o projeto e o WebService está funcionando perfeitamente em minha máquina.

Preciso coloca-lo em produção e para isso o projeto foi incluído em um servidor LINUX com o TomCat 5.5. Quando tento consumir o serviço, o seguinte erro é emitido:

Alguém já passou por isso? Faz ideia do que se trata ? Imagina ou sonha o que pode ser ? rs
Muito obrigado pela contribuição de todos.

Abraços

33 Respostas

altitdb

Creio eu que possa ser duas coisas.

Ou o servidor não tá aceitando o certificado,

ou o certificado não foi colocado corretamente no seu keystore.

Você precisa desses dois configurados corretamente pra consumir o serviço.

Abraço.

lblanco

Pois é,

Hoje a tarde fiz mais alguns testes e descobri que as vezes ele funciona, outras vezes não.
Para evitar este problema pensei em instalar o certificado no servidor, porém não tenho o arquivo do certifado, então acessando o internet explorer eu exportei-o.

Agora tenho um arquivo .cer, porém não tenho a senha.
Como posso fazer ?

altitdb

Se não me engano, acho que você consegue importar o arquivo .cer pro keystore sem ter a senha.

xD~~

lblanco

Olá,

Nada feito. Ele pede a senha e o usuário. Sem estas informações não é possível acessar o serviço.
Que coisa não !

altitdb

Tente criar outro e importar pro keystore.

xD~~

marcos1EM

altitdb, tive um problema semelhante e tive que fazer como está descrito no link abaixo:

http://www.exampledepot.com/egs/javax.net.ssl/TrustAll.html

balrog

usar a gambiarra do linkl acima eh a mesma coisa que nao usar SSL
faca o que foi sugerido acima, crie um novo SSC e instale o mesmo que vai funcionar

lblanco

Olá,

O que é SSC ?

Para importar o certificado na máquina linux é preciso do usuário e da senha do certificado. Já entrei em contato com a empresa fornecedora do serviço e estou aguardando o que eles vão me falar.

Quando conseguir algo publico aqui a solução encontrada.
Obrigado.

balrog

SSC = self signed certificate

agora se vc tem um certificado assinado por uma CA oficial, e nao sabe a senha ? ninguem merece neh…

siga as instrucoes nesse link http://docs.jboss.org/jbossweb/3.0.x/ssl-howto.html

lblanco

Pois é,

Eu acessei o link onde o serviço deve ser consumido. Exportei o certificado (.cer) para o meu computador e segui os passos para importa-lo no servidor usando o keytool, mas infelizmente o usuário e a senha são solicitados.

Andei pesquisando sobre o assunto e vi que a forma correta para se fazer isto é exatamente como descrevi acima, porém para isso preciso do usuário e da senha o certificado. Como já mencionei, já entrei em contato com a empresa que fornece o serviço e agora estou aguardando um retorno.

Não tenho muito o que fazer e desabilitar o certificado ( como o link acima ) não acho muito prudente, visto que se trata de informações confidenciais.
Muito obrigado para todos.

Assim que conseguir solicitar o problema, postarei aqui um passo-a-passo para a minha solução.
Muito obrigado.

lblanco

Ola,

Com a senha em mãos executei o seguinte comando no servidor:

E o webservice funcionou.
Muito obrigado a todos pelos posts.

Caso alguém tenha dúvidas, é só me procurar.
Será um prazer ajuda-los.

Obrigado.

lblanco

Galera,

Achei que havia conseguido fazer o trem funcionar, mas pelo visto nada. Estou ficando aborrecido com isto já. Estou apanhando muito para fazer o meu webservice client falar com um serviço que tem HTTPS.

O que eu já fiz foi:

1 - Exportei o certificado .cer usando o internet explorer.

2 - No servidor linux usei o seguinte comando para importar o bendito do certificado:

SRVCBI03:/usr/java/jdk1.6.0_25/bin # keytool -import -alias meuteste -file meucertificado.cer -keystore cacerts -trustcacerts

3 - no meu código, inclui o seguinte trecho de código

System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
            System.setProperty("javax.net.ssl.trustStoreType", "JKS");
            System.setProperty("javax.net.ssl.trustStore", "caminhodocertificado");
            System.setProperty("javax.net.ssl.keyStorePassword", "12345"); -- senha que coloquei na importacao do certificado.

4 - O erro que recebo é este:

Preciso de ajuda.
Não tenho mais forças para prosseguir sozinho rs.
Abraços e confiante que alguma alma caridosa e fuçada irá me ajudar rs

Obrigado.

altitdb

Amigo,

você informou apenas os valores do certificado.

Pra consumir você precisa informar os valores do keystore também.

Não desanime não, Web Services com HTTPS são dificeis mesmo.

Mais com o tempo você pega a moral…

xD~~

lblanco

Pois é,

É nisto que eu estou apanhando. O que vem a ser o keystore ? Tenho um certificado .cer, então pensei que ao importa-lo com o comando acima ele já estaria em meu repositório de certificados. Você consegue me ajudar ? Preciso terminar este trabalho que já está me tomando mais tempo do que havia planejado.

Os passos que fiz acima estão corretos ? Falta apenas apontar o meu keystore ? Como posso fazer isso ?
Muito obrigado mesmo.

altitdb

Essa classe aqui vai te ajudar, basta você configurar com sua URL e porta, dai ela vai te gerar um arquivo cacerts (falei errado, não é keystore) pra você informar quando for consumir o serviço.

Eu ainda to quebrando a cabeça com alguns pontos de consumo. Algumas palavras parecidas e ainda to sem muito conceito!

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package nfe20;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLHandshakeException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

/**
 *
 * @author altitdb
 */
public class NFeBuildAllCacerts {

    private static final String JSSECACERTS = "nfe-cacerts";
    private static final int TIMEOUT_WS = 60;

    public static void main(String[] args) {
        try {
            /** 
             * Endereço do WebService. 
             * O Endereço abaixo é do Sefaz Virtual RS, altere para o endereço que 
             * for necessário. 
             */
//            String enderecoWebService = "homologacao.nfe2.fazenda.pr.gov.br";
            String enderecoWebService = "localhost";

//            File cacertsFile = gerarCacerts(enderecoWebService, 443);
            File cacertsFile = gerarCacerts(enderecoWebService, 8443);
            if (cacertsFile != null) {
                info("| Cacerts gerado em: " + cacertsFile.getAbsolutePath());
            }
        } catch (Exception e) {
            error(e.toString());
        }
    }

    public static File gerarCacerts(String host, int port) throws Exception {
        char[] passphrase = "changeit".toCharArray();

        File file = new File(JSSECACERTS);
        if (file.isFile() == false) {
            char SEP = File.separatorChar;
            File dir = new File(System.getProperty("java.home") + SEP + "lib" + SEP + "security");
            file = new File(dir, JSSECACERTS);
            if (file.isFile() == false) {
                file = new File(dir, "cacerts");
            }
        }

        info("| Loading KeyStore " + file + "...");
        InputStream in = new FileInputStream(file);
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(in, passphrase);
        in.close();

        SSLContext context = SSLContext.getInstance("TLS");
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(
                TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(ks);
        X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
        SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
        context.init(null, new TrustManager[]{tm}, null);
        SSLSocketFactory factory = context.getSocketFactory();

        info("| Opening connection to " + host + ":" + port + "...");
        SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
        socket.setSoTimeout(TIMEOUT_WS * 1000);
        try {
            info("| Starting SSL handshake...");
            socket.startHandshake();
            socket.close();
            info("| No errors, certificate is already trusted");
        } catch (SSLHandshakeException e) {
            /** 
             * PKIX path building failed: 
             * sun.security.provider.certpath.SunCertPathBuilderException: 
             * unable to find valid certification path to requested target 
             * Não tratado, pois sempre ocorre essa exceção quando o cacerts 
             * nao esta gerado. 
             */
        } catch (SSLException e) {
            error("| " + e.toString());
        }

        X509Certificate[] chain = tm.chain;
        if (chain == null) {
            info("| Could not obtain server certificate chain");
            return null;
        }

        info("| Server sent " + chain.length + " certificate(s):");
        MessageDigest sha1 = MessageDigest.getInstance("SHA1");
        MessageDigest md5 = MessageDigest.getInstance("MD5");
        for (int i = 0; i < chain.length; i++) {
            X509Certificate cert = chain[i];
            sha1.update(cert.getEncoded());
            md5.update(cert.getEncoded());

            String alias = host + "-" + (i);
            ks.setCertificateEntry(alias, cert);
            info("| Added certificate to keystore '" + JSSECACERTS + "' using alias '" + alias + "'");
        }

        File cafile = new File(JSSECACERTS);
        OutputStream out = new FileOutputStream(cafile);
        ks.store(out, passphrase);
        out.close();

        return cafile;
    }

    private static class SavingTrustManager implements X509TrustManager {

        private final X509TrustManager tm;
        private X509Certificate[] chain;

        SavingTrustManager(X509TrustManager tm) {
            this.tm = tm;
        }

        public X509Certificate[] getAcceptedIssuers() {
            throw new UnsupportedOperationException();
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            throw new UnsupportedOperationException();
        }

        public void checkServerTrusted(X509Certificate[] chain, String authType)
                throws CertificateException {
            this.chain = chain;
            tm.checkServerTrusted(chain, authType);
        }
    }

    private static void info(String info) {
        System.out.println("INFO: " + info);
    }

    private static void error(String error) {
        System.out.println("ERROR: " + error);
    }
}

Tá pra NF-e, mais serve pra qualquer Web Service.

xD~~

lblanco

Alterei o código conforme as sugestões:

System.setProperty("java.protocol.handler.pkgs", "com.sun.net.ssl.internal.www.protocol");
  Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

  System.setProperty("javax.net.ssl.keyStoreType", "PKCS12");
  System.setProperty("javax.net.ssl.keyStore", "caminho\certificado.cer");
  System.setProperty("javax.net.ssl.keyStorePassword", "senha");

  System.setProperty("javax.net.ssl.trustStoreType", "JKS");
  System.setProperty("javax.net.ssl.trustStore", "caminho\cacerts");
  System.setProperty("javax.net.ssl.keyStorePassword", "senha");

Agora temos o erro abaixo:

altitdb

Tente converter esse certificado .cer para .pfx.

PKCS12 é para .pfx ou .p12

xD~~

lblanco

É pra chorar rs.
Olhem a hora rs… estou aqui correndo atrás desse negocio.

Chutei o pau da barraca e tentei desativar a validação e mesmo assim o erro é este:

altitdb, não é possivel converter o .cer para pfx
Quanto as suas classes, muito obrigado mesmo. Como posso fazer para usa-las ?

Vejo que você tem duas. Em que momento devo instancia-las ?
Estou chegando ao ponto de desistir !

altitdb

É possivel sim, tem um programa que utilizo chamado KeyStore Explorer 4.0.1, ele faz esse serviço^^

Show de bola ele…

Essas classes você executa elas “avulsas” na verdade é só uma, dai ele te gera o arquivo!!

Você precisa gerar ele apenas uma vez.

xD~~

balrog

com openssl vc consegue fazer essa conversao

lblanco

Isto podia ser um pouco mais simples, ou pelo menos ter um pouco mais de material.
Vou ver se compro um livro para entender melhor sobre isso e então depois partir para o trabalho. Assim, na tentativa e erro é complicado. Acabo me irritando.

Veja o link que encontrei. Tem coisas aqui também:


http://www.jjocenio.com/2011/03/conexao-ssl-em-aplicacoes-java/

balrog

estava com a impressao de que vc javia resolvido o problema uma vez com a senha em maos, qual eh exatamente a dificuldade que vc esta tendo no momento? eh apenas o cliente que nao esta autenticando corretamente?

lblanco

Pois é,

Eu também achei que já tinha resolvido, mas não. Sinceramente, nem sei mais o que dizer. Fiz tudo o que precisava ser feito, importei o certificado usando o keytool, setei para não validar certificado, usei as dicas do blog acima e nada. Sempre recebo os mesmos erros. Ora o certificado não foi encontrado, ora o certificado não é valido e ora a url esta errada. Diante disso não sei mais o que fazer.

Lembrando que localmente , no meu computador a aplicação funciona sem problemas. Quando jogo ela no servidor tenho essas dificuldades.
Vou procurar algum livro na net falando sobre isso , não adianta ficar chutando para achar as soluções. Vou estudar primeiro sobre o assunto que a solução vem.

Se alguém estiver afim de dar uma aula, estou a aberto a aprender rs.
Meu skype é lucasblancob

Abraçosss

lblanco

Opa,

Respondendo a sua pergunta, o erro que estou empacado agora é:

balrog

esse erro eh relacionado ao fato da URL do seu servidor ser diferente da URL que o certificado foi emitido, o que normal quando vc esta usando um SSC (imagino que este seja seu caso)
ae que vem o lance de vc instruir a JRE que o seu certificado eh valido, e os erros de dominios incompativeis deveriam desaparecer

qual servidor vc usa? qual setup vc esta usando no conector?

lblanco

Eu utilizo o um servidor LINUX com a distribuição SUSE.
Estou utilizando o TomCat 5.5 e utilizo o conector padrão do TomCat, se eu não me engano é o OpenSSL !

Foi isto que me perguntou rs ?

balrog

sim, isso mesmo poste a configuracao do conector:

lblanco

No tomcat eu não fiz absolutamente nada.
Apenas acessei o servidor, usei o comando do Keytool para importar o certificado e em seguida usei o código abaixo para configurar a minha aplicação
para acessar o keystore gerado

System.setProperty("javax.net.ssl.trustStore", "/tmp/keystore.key");
 System.setProperty("javax.net.ssl.keyStorePassword", "12345");
balrog

porque nao?

balrog

um exemplo de conector configurado para SSL

&lt;Connector protocol="org.apache.coyote.http11.Http11Protocol"
           port="8443" minSpareThreads="5" maxSpareThreads="75"
           enableLookups="true" disableUploadTimeout="true" 
           acceptCount="100"  maxThreads="200"
           scheme="https" secure="true" SSLEnabled="true"
           keystoreFile="${jboss.server.home.dir}/conf/jboss-server-keystore.jks" 
	   keystorePass="changeit"
	   truststorefile="${jboss.server.home.dir}/conf/truststore.jks" 
	   truststorepass="changeit"
           clientAuth="false" sslProtocol="TLS"/&gt;

caso queira forcar o uso de client certs, apenas mude para clientAuth="true"

balrog

isso eh verdade, querer correr antes de saber caminhar nunca da muito certo

esse post explica o basico do basico que vc tem que entender (ele fala sobre o setup no weblogic weblogic, mas a mecanismo eh identico em qualquer servidor)

http://monduke.com/2006/06/04/the-fifteen-minute-guide-to-mutual-authentication/

lblanco

Eu não alterei o tomcat porque recebi instruções que uma vez que o código fosse colocado no meu programa, não seria necessário alterar as configurações.
De qualquer forma obrigado pela ajuda.

Vou estudar o assunto antes para não ficar falando besteira rs.
Obrigado.

D

Alguém pode me ajudar?

Estou tentando fazer funcionar um webservice acessar um https, eu estava fazendo com System.properties na aplicação, passando como parametro os certificados.
Quando migramos para o Weblogic isso parou de funcionar.

Esse weblogic, tem alguma mágica pra fazer ele respeitar o System.properties da minha aplicação?

Parece que ele reseta a conexão.

Obrigado

Criado 15 de junho de 2011
Ultima resposta 11 de mar. de 2014
Respostas 33
Participantes 5