Web Service Client com acesso HTTPS

33 respostas
L

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

A

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.

L

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 ?

A

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

xD~~

L

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 !

A

Tente criar outro e importar pro keystore.

xD~~

M

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

B

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

L

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.

B

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

L

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.

L

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.

L

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.

A

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~~

L

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.

A

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~~

L

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:

A

Tente converter esse certificado .cer para .pfx.

PKCS12 é para .pfx ou .p12

xD~~

L

É 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 !

A

É 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~~

B

com openssl vc consegue fazer essa conversao

L

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/

B

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?

L

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

L

Opa,

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

B

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?

L

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 ?

B

sim, isso mesmo poste a configuracao do conector:

L

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");
B

porque nao?

B

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"

B

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/

L

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