Como o Java trabalha com Certificados Digitais


Toda a comunicação com os WebServices do SEFAZ se dá através de uma comunicação segura viabilizada pela utilização de Certificados Digitais.

Se você está lendo este post, com certeza já deve ter conhecimento do que é um Certificado Digital e para que serve.

Mas, caso isto seja novo para você, basta saber que o Certificado Digital é um arquivo (no caso de certificados A1) ou um dispositivo, como um cartão ou token (no caso de certificados A3) que sua empresa adquire junto ao ICP-Brasil (mediantes locais credenciados, como  os Correios, por exemplo) e que são utilizados na sua comunicação web com a SEFAZ. Através deste certificado, que deve estar no seu computador (A1) ou conectados a ele (A3) a Receita Federal tem a sua “assinatura”, a segurança de que você é quem diz ser.

O Certificado Digital será utilizado por nós em dois momentos:

 

1 – Quando acessamos os WebServices do Sefaz

2 – Quando assinamos alguns (não todos) arquivos XML para transmissão

 

Não é o intuito deste post discursar sobre chave pública e privada, criptografia, segurança digital e implicações na utilização de Certificados. Como falamos, este grupo prioriza a praticidade. Ou seja, pouca teoria e mais prática (teoria tem aos montes por ai, basta dar uma “googlada”). Portanto, veremos aqui, como acessar os servidores do Sefaz mediante uma comunicação segura via Java, utilizando certificados do tipo A1 (em formato de arquivo).

 

KeyStore e TrustStore

Para que você possa acessar os servidores do Sefaz você deve garantir a eles quem você é e, também, ter a garantia de que eles são quem dizem ser.

O KeyStore é o repositório (banco de dados) do Java onde você armazena SEUS certificados digitais, ou seja, suas assinaturas, as credencias que confirmam sua identidade.

O TrustStore é um repositório de certificados de terceiros, digamos assim. Nele são registrados os certificados de confiança do cliente, neste caso os certificados de cada um dos Sefaz que você pretende acessar.

Em resumo, o KeyStore é utilizado para autenticar um cliente (garante que você é quem diz ser) e o TrusStore para autenticar um servidor (garante que ele é quem diz ser).

Desta forma, quando você acessar o WebService de envio de uma NF-e/NFC-e, por exemplo, sua identidade será confirmada pelos registro contido no KeyStore e a identidade do Sefaz do seu estado  pelos registros do TrustStore.

 

Gerando KeyStore e TrustStore

Você deve estar pensando: Ok, muito bem, compreendi o que são esses camaradas ai, mas onde eles estão? Como os configuro? Como os acesso? De onde venho? Para onde vou?

Na verdade, apesar do nome feio deles, é relativamente fácil trabalhar com KeyStore e TrustStore, uma vez que não são nada mais, nada menos, que arquivos que serão gerados e armazenados no computador que acessará os serviços da receita federal.

 

Primeiro o KeyStore

Como é necessário somente um certificado para acessarmos os WebServices da Receita Federal nosso KeyStore será nosso próprio certificado, este acrescido da cadeia de certificados da AC, para que seja aceito corretamente.

Para gerar este “certificado completo” basta utilizar o assistente de certificados do Windows para importar seu certificado e, a seguir, exportá-lo juntamente com sua cadeia de certificados. Vamos ver como fazer isso agora.

 

Importando o Certificado Digital

Siga o passo-a-passo:

1. Dê dois cliques no seu Certificado Digital (em nosso exemplo, o chamaremos de SEU_CERTIFICADO.pfx)

 

2. Aparecerá a seguinte tela:

 

 

3. Clique em avançar. O Assistente lhe pedirá o nome, ou localização do seu certificado. Como executamos o assistente dando dois cliques sobre o certificado ele já aparece selecionado. Clique em avançar.

 

4. Agora muita atenção, este passo é fundamental. Informe a senha do seu certificado (que lhe é fornecida juntamente com o mesmo) e, a seguir, marque a opção “Marcar esta chave como exportável…”. É esta opção que vai permitir que, logo a seguir, venhamos a exportar nosso certificado com toda a cadeia de certificados da AC. Clique em Avançar.

5. Na tela a seguir, deixe a primeira opção selecionada (isso não vai importar para nós futuramente, uma vez que o Java não se utiliza dos locais de armazenamento de certificados do Windows) e pressione Avançar.

 

 

6. A próxima tela informa onde o nome do certificado, o tipo de conteúdo e o local onde o mesmo será armazenado. Clique em Concluir.

 

7. Se tudo correu bem, a importação será concluída

 

Se você recebeu a mensagem a cima, conseguimos importar nosso certificado sem problemas. Agora, vamos exporta-lo para pegarmos a nossa cadeia de certificados.

 

 

Exportando o Certificado Digital com a Cadeia de Certificados

 

1. Primeiramente devemos acessar a área de armazenamento de certificados do Windows. Para isso, abra o Painel de Controle do Windows (Iniciar->Painel de Controle) e clique sobre o ícone “Opções de Internet”

 

2. Na aba “Pessoal”, na lista de certificados que aparecer, selecione o certificado que acabamos de importar e clique em Exportar.

 

3. A seguinte tela irá aparecer. Clique em Avançar.

 

4. Muita atenção aqui. Selecione a opção “Sim, exportar a chave particular”. Esta opção vai permitir que, logo a seguir, você exporte o certificado com a cadeia de certificados.

 

5. Aqui está a jogada. Selecione a opção “Incluir todos os certificados no caminho de certificação, se possível”. Esta opção exportará todos os demais certificados necessários para nós. Deixa a segunda opção selecionada e a ultima desmarcada, tal como está. Clique em Avançar.

6. Especifique a senha do seu certificado (aquele que você recebeu junto com seu certificado), confirme a senha e clique em Avançar.

 

7. Agora especifique um local e nome para o novo certificado a ser gerado. Especifiquei arqui “C:\certificado_full”. Note que não precisa digitar a extensão do arquivo. Clique em Avançar.

8. Estamos quase terminando. Neste momento o Assistente para exportação de certificados lhe mostra-rá um resumo do que foi feito até aqui:

Nome do arquivo: C:\certificado_full.pfx

Chaves de Exportação: sim

Incluir todos os certificados no caminho de certificação: sim

Formato do arquivo: Troca de informações pessoais (*.pfx)

 

Clique em Concluir.

 

8. Se tudo deu certo, aparecerá a seguinte mensagem

 

Ok, exportamos nosso certificado com toda a cadeia de certificados da Autoridade Certificadora. A partir de agora não utilizaremos mais o certificado “SEU_CERTIFICADO.pfx” (nosso certificado original de exemplo), pois passaremos a usar o “CERTIFICAL_FULL.pfx” que acabamos de criar.

Mais tarde, neste capítulo, veremos como associar no certificado ao KeyStore do Java.

 

Configuraco o TrustStore

Muito bem, até o presente momento fizemos tudo para mostrar para os servidores da Receita Federal que nós somos, realmente, quem afirmamos ser. Agora, nada mais justo do que dizer para eles: “auto lá, Identifique-se!”. Para isso nos utilizaremos do TrustStore.

Como falamos anteriormente, o TrustStore é um banco de dados (um arquivo .jks) que contém o registro dos certificados que julgamos confiáveis. Adicionaremos, então, ao TrustStore os certificados do Sefaz de cada Estado que desejamos acessar. Varemos um exemplo com o webservice homologação.nfe.sefazvirtual.rs.gov.br para entendermos o processo e, a seguir, veremos uma forma mais prática de fazer isso.

Ok, para adicionarmos o certificado do sefazvirtual ao nosso TrustStore é necessário termos ele em mãos, e a seguir o adicionar ao nosso banco de dados. Mas onde adquirir este certificado, e como adiciona-lo ao TrustStore? Existem algumas formas por ai, mas a mais prática que encontrei, e que faz as duas funções (adquirir o certificado e registrar) de uma vez só se chama InstallCert.java.

 

Utilizando o InstallCert.java

O InstallCert.java, como podemos ver, é uma classe Java disponibilizada no blog da Sun e que acessa um servidor especifico, listando os certificados digitais oferecidos pelo mesmo e adicionando o certificado que desejarmos a um arquivo .jks (um arquivo TrustStore).

O código completo da classe InstallCert segue adiante:

 

InstallCert.java

/*
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* – Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* – Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* – Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS
* IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* http://blogs.sun.com/andreas/resource/InstallCert.java
* Use:
* java InstallCert hostname
* Example:
*% java InstallCert ecc.fedora.redhat.com
*/

import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

/**
* Class used to add the server’s certificate to the KeyStore
* with your trusted certificates.
*/
public class InstallCert {

public static void main(String[] args) throws Exception {
String host;
int port;
char[] passphrase;
if ((args.length == 1) || (args.length == 2)) {
String[] c = args[0].split(“:”);
host = c[0];
port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
String p = (args.length == 1) ? “changeit” : args[1];
passphrase = p.toCharArray();
} else {
System.out.println(“Usage: java InstallCert <host>[:port] [passphrase]”);
return;
}

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”);
}
}
System.out.println(“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();

System.out.println(“Opening connection to ” + host + “:” + port + “…”);
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.setSoTimeout(10000);
try {
System.out.println(“Starting SSL handshake…”);
socket.startHandshake();
socket.close();
System.out.println();
System.out.println(“No errors, certificate is already trusted”);
} catch (SSLException e) {
System.out.println();
e.printStackTrace(System.out);
}

X509Certificate[] chain = tm.chain;
if (chain == null) {
System.out.println(“Could not obtain server certificate chain”);
return;
}

BufferedReader reader =
new BufferedReader(new InputStreamReader(System.in));

System.out.println();
System.out.println(“Server sent ” + chain.length + ” certificate(s):”);
System.out.println();
MessageDigest sha1 = MessageDigest.getInstance(“SHA1”);
MessageDigest md5 = MessageDigest.getInstance(“MD5″);
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = chain[i];
System.out.println
(” ” + (i + 1) + ” Subject ” + cert.getSubjectDN());
System.out.println(” Issuer ” + cert.getIssuerDN());
sha1.update(cert.getEncoded());
System.out.println(” sha1 ” + toHexString(sha1.digest()));
md5.update(cert.getEncoded());
System.out.println(” md5 ” + toHexString(md5.digest()));
System.out.println();
}

System.out.println(“Enter certificate to add to trusted keystore or ‘q’ to quit: [1]”);
String line = reader.readLine().trim();
int k;
try {
k = (line.length() == 0) ? 0 : Integer.parseInt(line) – 1;
} catch (NumberFormatException e) {
System.out.println(“KeyStore not changed”);
return;
}

X509Certificate cert = chain[k];
String alias = host + “-” + (k + 1);
ks.setCertificateEntry(alias, cert);

OutputStream out = new FileOutputStream(“jssecacerts”);
ks.store(out, passphrase);
out.close();

System.out.println();
System.out.println(cert);
System.out.println();
System.out.println
(“Added certificate to keystore ‘jssecacerts’ using alias ‘”
+ alias + “‘”);
}

private static final char[] HEXDIGITS = “0123456789abcdef”.toCharArray();

private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int b : bytes) {
b &= 0xff;
sb.append(HEXDIGITS[b >> 4]);
sb.append(HEXDIGITS[b & 15]);
sb.append(‘ ‘);
}
return sb.toString();
}

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

}

Compile esta classe normalmente (javac InstallCert.java) e, a seguir, em um prompt de comando, execute o seguinte comando para rodar o programa:

 

java InstallCert homologação.nfe.sefazvirtual.rs.gov.br

Este comando irá acessar o webservice sefezvirtual do Rio Grande do Sul e listar seus certificados. Depois disso devemos selecionar qual certificado desejamos adicionar o TrusStore digitando o número correspondente do mesmo. Se desejar adicionar o primeiro certificado digite 1, se o segundo digite 2, e assim por diante.

 

 

Digite 1 para selecionar o primeiro certificado e pressione Enter.

O InstallCert irá realizar algumas operações e, se tudo der certo, finalizará com a seguinte mensagem “Added certificate to keystore ‘jssecacerts’ using alias ‘homologacao.nfe.sefazvirtual.rs.gov.br-1’”, conforme a figura a seguir:

 

Isso nos indica que o InstallCert gerou uma nova TrustStore chamada “jssecacerts”, localizada no diretório em que foi executado. Neste TrustStore o certificado foi adicionado e será referenciado pelo alias (apelido) ‘homologacao.nfe.sefazvirtual.rs.gov.br-1’. Veja na figura a baixo o nosso TrustStore criado e pronto para ser utilizado:

 

 

A senha de acesso do arquivo jsscacerts é, como podemos ver no código fonte: “changeit”. Como é sugerido, se desejar você alterar a senha no código, recompilar e executar o programa novamente.

 

Tornando a vida mais fácil

Muito bem, conseguimos até aqui configurar nosso Certificado Digital para comprovar nossa identidade e nosso TrustStore para comprovar a identidade do SefazVirtual do Rio Grande do Sul, e apenas do SefazVirtual do Rio Grande do Sul! Aqui temos um pequeno problema: existem inúmeros webservices do projeto NF-e/NFC-e no Brasil. Cada estado tem seus webservices de homologação e produção. Então deveremos conhecer o endereço de cada um deles e adiciona-los manualmente ao nosso TrustStore jsscacerts? Sim, isso mesmo! Mas calma, não se desespere. Podemos resolver este problema de duas formas: criando um script para executar esta função para nós (chamar o InstallCert para uma lista de webservices previamente preparada por nós) ou utilizar uma classe que alguma alma caridosa disponibilizou na internet após passar pelo mesmo sufoco que nós. Esta segunda opção parece melhor, não é? Navegando na internet encontrei a seguinte classe que podemos utilizar:

 

GerarCacertsNfe.java

/*

* Encontrado no forum do www.guj.com.br

*/

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;

 

public class GerarCacertsNfe {

private static final String JSSECACERTS = “NFeCacerts”;

private static final int TIMEOUT_WS = 30;

 

public static void main(String[] args) {

try {

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();

 

/**

* AM – 2.00: homnfe.sefaz.am.gov.br

* BA – 2.00: hnfe.sefaz.ba.gov.br

* CE – 2.00: nfeh.sefaz.ce.gov.br

* GO – 2.00: homolog.sefaz.go.gov.br

* MG – 2.00: hnfe.fazenda.mg.gov.br

* MS – 2.00: homologacao.nfe.ms.gov.br

* MT – 2.00: homologacao.sefaz.mt.gov.br

* PE – 2.00: nfehomolog.sefaz.pe.gov.br

* PR – 2.00: homologacao.nfe2.fazenda.pr.gov.br

* RS – 2.00: homologacao.nfe.sefaz.rs.gov.br

* SP – 2.00: homologacao.nfe.fazenda.sp.gov.br

* SCAN – 2.00: hom.nfe.fazenda.gov.br

* SVAN – 2.00: hom.sefazvirtual.fazenda.gov.br

* SVRS – 2.00: homologacao.nfe.sefazvirtual.rs.gov.br

*/

get(“homnfe.sefaz.am.gov.br”, 443, ks);

get(“hnfe.sefaz.ba.gov.br”, 443, ks);

get(“nfeh.sefaz.ce.gov.br”, 443, ks);

get(“homolog.sefaz.go.gov.br”, 443, ks);

get(“hnfe.fazenda.mg.gov.br”, 443, ks);

get(“homologacao.nfe.ms.gov.br”, 443, ks);

get(“homologacao.sefaz.mt.gov.br”, 443, ks);

get(“nfehomolog.sefaz.pe.gov.br”, 443, ks);

get(“homologacao.nfe2.fazenda.pr.gov.br”, 443, ks);

get(“homologacao.nfe.sefaz.rs.gov.br”, 443, ks);

get(“homologacao.nfe.fazenda.sp.gov.br”, 443, ks);

get(“hom.nfe.fazenda.gov.br”, 443, ks);

get(“hom.sefazvirtual.fazenda.gov.br”, 443, ks);

get(“homologacao.nfe.sefazvirtual.rs.gov.br”, 443, ks);

 

File cafile = new File(JSSECACERTS);

OutputStream out = new FileOutputStream(cafile);

ks.store(out, passphrase);

out.close();

} catch (Exception e) {

e.printStackTrace();

}

}

 

public static void get(String host, int port, KeyStore ks) throws Exception {

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”);

}

 

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 + “‘”);

}

}

 

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 log) {

System.out.println(“INFO: ” + log);

}

 

private static void error(String log) {

System.out.println(“ERROR: ” + log);

}

 

}

 

 

Compile este programa e execute com a seguinte linha de comando:

 

java GerarCacertsNfe

 

Será gerado o arquivo jsscacerts que iremos renomear para NFeCacerts.

 

Muito bem, de posso do certificado (certificado_full.) e do TrusStore (NfeCacerts) vamos configurar o Java para acessar o webservice da Receita e ser reconhecido por ele.

 

 

Conectando de Forma Autenticada no WebService

Para utilizarmos nossas credenciais em um sistema Java nós devemos utilizar a função System.setProperty() para setarmos as propriedades do javax.ssl, o pacote de segurança do Java.

A idéia básica é a seguinte:

1. Limpo as propriedades

2. Configuro o KeyStore apontando para o certificado do cliente

3. Configura o TrustStore apontando para o arquivo NfeCacerts

4. Crio uma mensagem SOAP, que será enviada para o WebService

5. Instancio uma conexão SOAP

6. Envio a mensagem e retorno seu resultado

 

Nada muito complicado. Veremos cada um destes passsos separadamente, e no final veremos o código completo.

 

Limpando as propriedades

Use o seguinte código para evitar erros. É somente uma medida de segurança para não corrermos o risco de usarmos outro certificado:

 

System.clearProperty(“javax.net.ssl.keyStore”);

System.clearProperty(“javax.net.ssl.keyStorePassword”);

System.clearProperty(“javax.net.ssl.trustStore”);

 

Configurando o KeyStore

A seguir especificamos o tipo do KeyStore, a localização e a senha.

PKCS12 informa ao sistema que estamos utilizando um certificado do tipo A1, ou seja, um arquivo armazenado no disco rígido.

 

System.setProperty(“javax.net.ssl.keyStoreType”, “PKCS12”);

System.setProperty(“javax.net.ssl.keyStore”, “C:/CERTIFICADO_FULL.pfx”);

System.setProperty(“javax.net.ssl.keyStorePassword”, “123456”);

 

Troque o “123456” pela senha do seu Certificado Digital.

Configurando o TrustStore

Configuramos agora o TrustStore que geramos anteriormente. Novamente aqui nada complicado. O tipo informado é JKS (Java Key Store).

 

System.setProperty(“javax.net.ssl.trustStoreType”, “JKS”);

System.setProperty(“javax.net.ssl.trustStore”, “C:/NfeCacerts”);

System.setProperty(“javax.net.ssl.trustStorePassword”, “123456”);

Troque o “123456” pela senha do seu TrustStore.

Isso é tudo que precisamos fazer para acessarmos os servidores do Sefaz de forma segura. Agora veremos como enviar uma mensagem SOAP para o mesmo!

 

Criado uma mensagem SOAP

Para enviarmos uma mensagem aos WebServices da Receita são necessárias duas coisas:

1. A URL do servidor que desejamos acessar

2. A Mensagem a ser enviada, que será nossa requisição em XML dentro de um envelope SOAP

 

3. Criando um objeto URL que apontará para o servidor

URL url = new URL(urlAddress);

 

4. Transformando nosso envelope SOAP em um ByteArrayInputStream

ByteArrayInputStream  envelope = new ByteArrayInputStream(envelope.getBytes());

 

5. Criamos uma fabrica de mensages, informando o protocolo que iremos utilizar: SOAP1.2:

MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);

 

6. Criamos um header que informará o tipo de mensagem que estamos enviando

MimeHeaders header = new MimeHeaders();

header.addHeader(“Content-Type”, “application/soap+xml”);

 

7. Instanciamos a classe SOAMessage gerando o objeto message. Observe que utilizamos nossa fábrica de mensagens, e esta recebe como parâmetro o header (cabeçalho da mensagem) e o envelope SOAP

SOAPMessage message = factory.createMessage(header, envelope);

 

8. Instanciamos a classe SOAPConnection gerando uma conexao SOAP

SOAPConnection conSoap = SOAPConnectionFactory.newInstance().createConnection();

 

9. Aqui enviamos nossa mensagem para o WebService capturando o retorno em um objeto do tipo SOAPMessage:

SOAPMessage resWs = conSoap.call(message, url);

 

10. Feito isso, imprimimos na saida padrão a resposta do WebService

ByteArrayOutputStream out = new ByteArrayOutputStream();

resWs.writeTo(out);

System.out.println(“out :\n” + out.toString());

 

Veja como fica tudo isso em uma função:

private static void AcessarWsComAutenticacao(String urlAddress, String envelope) {

try

{

System.setProperty(“java.protocol.handler.pkgs”, “com.sun.net.ssl.internal.www.protocol“);

Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());

/*

* limpo propriedades

*/

System.clearProperty(“javax.net.ssl.keyStore”);

System.clearProperty(“javax.net.ssl.keyStorePassword”);

System.clearProperty(“javax.net.ssl.trustStore”);

/*

* dados do certificado do cliente

*/

System.setProperty(“javax.net.ssl.keyStoreType”, “PKCS12”);

System.setProperty(“javax.net.ssl.keyStore”, “C:/CERTIFICADO_FULL.pfx”);

System.setProperty(“javax.net.ssl.keyStorePassword”, “123456”);

/*

* dados do certificado do servidor

*/

System.setProperty(“javax.net.ssl.trustStoreType”, “JKS”);

System.setProperty(“javax.net.ssl.trustStore”, “C:/NfeCacerts”);

System.setProperty(“javax.net.ssl.trustStorePassword”, “123456”);

/* Url do WebService */

URL url = new URL(urlAddress);

/* tipo de mensagem: SOAP */

MimeHeaders header = new MimeHeaders();

header.addHeader(“Content-Type”, “application/soap+xml”);

/* monta a mensagem SOAP */

MessageFactory factory = MessageFactory.newInstance(SOAPConstants.SOAP_1_2_PROTOCOL);

SOAPMessage message = factory.createMessage(header, new ByteArrayInputStream(envelope.getBytes()) );

/* instancia uma conexao SOAP */

SOAPConnection conSoap = SOAPConnectionFactory.newInstance().createConnection();

/* Envia a mensagem SOAP ao WebService */

SOAPMessage resWs = conSoap.call(message, url);

/* Mostra a mensagem de retorno */

ByteArrayOutputStream out = new ByteArrayOutputStream();

resWs.writeTo(out);

System.out.println(“out :\n” + out.toString());

}catch(Exception ex) {

System.out.println(“Erro: ” + ex.getMessage() );

}

}

Por enquanto é isso!

Para saber mais, acesse os outros posts deste grupo.

Abraço.

Ivan S. Vargas

ivan@is5.com.br

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s