Web Service Client com acesso HTTPS

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

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.

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 ?

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

xD~~

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 !

Tente criar outro e importar pro keystore.

xD~~

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

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

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.

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

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.

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.

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.

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

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.

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

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:

Tente converter esse certificado .cer para .pfx.

PKCS12 é para .pfx ou .p12

xD~~

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

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