Soap Request 403 Forbidden

Asked

Viewed 843 times

0

Hello folks please I need your help.

I’m trying to send make the connection to the esocial api but I got the 403 return Forbidden, I’m with updated certificate and using jks. Below is the section where I load the certificate to make the request with webServiceTemplate

 package br.jus.tjba.esocial.config;  

import java.io.InputStream;  
import java.net.Socket;  
import java.security.*;  
import java.security.cert.Certificate;  
import java.security.cert.X509Certificate;  

import javax.crypto.Cipher;  
import javax.crypto.SecretKey;  
import javax.net.ssl.KeyManager;  
import javax.net.ssl.SSLContext;  
import javax.net.ssl.TrustManager;  
import javax.net.ssl.TrustManagerFactory;  
import javax.net.ssl.X509KeyManager;  

import org.apache.http.client.HttpClient;  
import org.apache.http.conn.ssl.NoopHostnameVerifier;  
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;  
import org.apache.http.impl.client.HttpClientBuilder;  
import org.springframework.beans.factory.annotation.Value;  
import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
import org.springframework.core.io.Resource;  
import org.springframework.ws.client.core.WebServiceTemplate;  
import org.springframework.ws.transport.http.HttpComponentsMessageSender;  
import org.springframework.ws.transport.http.HttpComponentsMessageSender.RemoveSoapHeadersInterceptor;  

import br.jus.tjba.esocial.util.WsUtils;  

/** 
* 
* @author Rafael Vasco, Vinicius Cidreira 
*/  
@Configuration  
public class WsConfig {  

    @Value("${serpro.ssl.key-store}")  
    private Resource resourceKeyStore;  
    @Value("serpro.ssl.privatekey-store")  
    private Resource privateKey;  

    @Value("${serpro.ssl.key-store-password}")  
    private String resourceKeyStorePassword;  

    @Value("${serpro.ssl.private-key}")  
    private String privateKeyStorePassword;  

    @Value("${serpro.ssl.alias}")  
    private String alias;  

    @Value("${serpro.protocol}")  
    private String protocol;  

    @Bean  
    public WebServiceTemplate webServiceTemplate() throws Exception {  
        WebServiceTemplate webServiceTemplate = new WebServiceTemplate();  
        webServiceTemplate.setMessageSender(httpComponentsMessageSender());  

        return webServiceTemplate;  
    }  

    public HttpComponentsMessageSender httpComponentsMessageSender() throws Exception {  
        HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender();  
        httpComponentsMessageSender.setHttpClient(httpClient());  

        return httpComponentsMessageSender;  
    }  

    public HttpClient httpClient() throws Exception {  
        return HttpClientBuilder.create().setSSLSocketFactory(sslConnectionSocketFactory())  
                .addInterceptorFirst(new RemoveSoapHeadersInterceptor())  
                .build();  
    }  

    public SSLConnectionSocketFactory sslConnectionSocketFactory() throws Exception {  
        // NoopHostnameVerifier essentially turns hostname verification off as otherwise  
        // following error  
        // is thrown: java.security.cert.CertificateException: No name matching  
        // localhost found  
        return new SSLConnectionSocketFactory(sslContext(), NoopHostnameVerifier.INSTANCE);  
    }  

    public SSLContext sslContext() throws Exception {  

        SSLContext sslContext = SSLContext.getInstance(protocol);  

        KeyStore keyStore = WsUtils.loadKeyStore(resourceKeyStore.getInputStream(), resourceKeyStorePassword.toCharArray());  
        PrivateKey privateKey = null;  
        try {  
            privateKey = (PrivateKey) keyStore.getKey(  
                    alias,  
                    privateKeyStorePassword.toCharArray()  
            );  
        } catch (Exception e) {  
            e.getMessage();  
            e.printStackTrace();  
        }  
        InputStream fileCacerts = WsUtils.getCacert();  
        X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias);  

        final KeyManager[] keyManagers = createKeyManagers(keyStore, alias, certificate, privateKey);  
        final TrustManager[] trustManagers = createTrustManagers(fileCacerts);  
        sslContext.init(keyManagers, trustManagers, null);  
        fileCacerts.close();  

        return sslContext;  

    }  

    private KeyManager[] createKeyManagers(KeyStore keyStore, String alias, X509Certificate certificate, PrivateKey privateKey) {  
        return new KeyManager[]{new NFKeyManager(keyStore, alias, certificate, privateKey)};  
    }  

    private TrustManager[] createTrustManagers(InputStream fileCacerts) throws Exception {  
        final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());  
        KeyStore trustStore = KeyStore.getInstance("JKS");  
        trustStore.load(fileCacerts, resourceKeyStorePassword.toCharArray());  
        trustManagerFactory.init(trustStore);  
        return trustManagerFactory.getTrustManagers();  
    }  


    class NFKeyManager implements X509KeyManager {  

        private final X509Certificate certificate;  
        private final PrivateKey privateKey;  
        private KeyStore keyStore;  
        private String alias;  

        NFKeyManager(KeyStore keyStore, String alias, final X509Certificate certificate, final PrivateKey privateKey) {  
            this.certificate = certificate;  
            this.privateKey = privateKey;  
            this.keyStore = keyStore;  
            this.alias = alias;  
        }  

        @Override  
        public String chooseClientAlias(final String[] arg0, final Principal[] arg1, final Socket arg2) {  
            return this.certificate.getIssuerDN().getName();  
        }  

        @Override  
        public String chooseServerAlias(final String arg0, final Principal[] arg1, final Socket arg2) {  
            return null;  
        }  

        @Override  
        public X509Certificate[] getCertificateChain(final String arg0) {  
            try {  
                Certificate[] certificates = keyStore.getCertificateChain(alias);  
                X509Certificate[] x509Certificates = new X509Certificate[certificates.length];  
                System.arraycopy(certificates, 0, x509Certificates, 0, certificates.length);  
                return x509Certificates;  
            } catch (KeyStoreException e) {  
                return new X509Certificate[]{this.certificate};  
            }  
        }  

        @Override  
        public String[] getClientAliases(final String arg0, final Principal[] arg1) {  
            return new String[]{this.certificate.getIssuerDN().getName()};  
        }  

        @Override  
        public PrivateKey getPrivateKey(final String arg0) {  
            return this.privateKey;  
        }  

        @Override  
        public String[] getServerAliases(final String arg0, final Principal[] arg1) {  
            return null;  
        }  
    }  

}  

here the xml generated for sending

<?xml version="1.0" encoding="UTF-8"?>  
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:v1="http://www.esocial.gov.br/schema/lote/eventos/envio/v1_1_1">  
   <soap:Body>  
      <v1:EnviarLoteEventos>  
         <v1:loteEventos>  
            <eSocial xmlns="http://www.esocial.gov.br/schema/lote/eventos/envio/v1_1_1">  
               <envioLoteEventos grupo="1">  
                  <ideEmpregador>  
                     <tpInsc>1</tpInsc>  
                     <nrInsc>13100760</nrInsc>  
                  </ideEmpregador>  
                  <ideTransmissor>  
                     <tpInsc>1</tpInsc>  
                     <nrInsc>131007221111444</nrInsc>  
                  </ideTransmissor>  
                  <eventos>  
                     <evento Id="ID1131007220000002019081317143000001">  
                        <eSocial xmlns="http://www.esocial.gov.br/schema/evt/evtInfoEmpregador/v02_04_02">  
                           <idEvento>ID11310072200888888888081317143555555</idEvento>  
                           <evtInfoEmpregador Id="ID1131007220000002019081317143000001">  
                              <ideEmpregador>  
                                 <tpInsc>1</tpInsc>  
                                 <nrInsc>13100722</nrInsc>  
                              </ideEmpregador>  
                              <infoEmpregador>  
                                 <inclusao>  
                                    <idePeriodo>  
                                       <iniValid>2019-07</iniValid>  
                                    </idePeriodo>  
                                    <infoCadastro>  
                                       <nmRazao>TJBAA</nmRazao>  
                                       <classTrib>85</classTrib>  
                                       <natJurid>1082</natJurid>  
                                       <indCoop>0</indCoop>  
                                       <indConstr>0</indConstr>  
                                       <indDesFolha>0</indDesFolha>  
                                       <indOptRegEletron>1</indOptRegEletron>  
                                       <indEntEd>N</indEntEd>  
                                       <indEtt>N</indEtt>  
                                       <contato>  
                                          <nmCtt>TESTE PIMENTA</nmCtt>  
                                          <cpfCtt>78177766520</cpfCtt>  
                                          <foneFixo>7133721896</foneFixo>  
                                          <foneCel>71988925970</foneCel>  
                                       </contato>  
                                       <infoOP>  
                                          <indUGRPPS>N</indUGRPPS>  
                                          <esferaOP>2</esferaOP>  
                                          <poderOP>2</poderOP>  
                                          <vrTetoRem>33763</vrTetoRem>  
                                          <ideEFR>N</ideEFR>  
                                          <cnpjEFR>13937032000160</cnpjEFR>  
                                       </infoOP>  
                                       <infoOrgInternacional>  
                                          <indAcordoIsenMulta>0</indAcordoIsenMulta>  
                                       </infoOrgInternacional>  
                                       <softwareHouse>  
                                          <cnpjSoftHouse>13100722</cnpjSoftHouse>  
                                          <nmRazao>TESTE TESTE</nmRazao>  
                                          <nmCont>LEANDRO SADY RODRIGUES</nmCont>  
                                          <telefone>71999999999</telefone>  
                                          <email>[email protected]</email>  
                                       </softwareHouse>  
                                       <infoComplementares>  
                                          <situacaoPJ>  
                                             <indSitPJ>0</indSitPJ>  
                                          </situacaoPJ>  
                                       </infoComplementares>  
                                    </infoCadastro>  
                                 </inclusao>  
                              </infoEmpregador>  
                           </evtInfoEmpregador>  
                           <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">  
                              <SignedInfo>  
                                 <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />  
                                 <SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />  
                                 <Reference URI="">  
                                    <Transforms>  
                                       <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />  
                                       <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" />  
                                    </Transforms>  
                                    <DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />  
                                    <DigestValue>[...]</DigestValue>  
                                 </Reference>  
                              </SignedInfo>  
                              <SignatureValue>[...]</SignatureValue>  
                              <KeyInfo>  
                                 <X509Data>  
                                    <X509Certificate>[...]</X509Certificate>  
                                 </X509Data>  
                              </KeyInfo>  
                           </Signature>  
                        </eSocial>  
                     </evento>  
                  </eventos>  
               </envioLoteEventos>  
            </eSocial>  
         </v1:loteEventos>  
      </v1:EnviarLoteEventos>  
   </soap:Body>  
</soap:Envelope> 

Here’s the excerpt where I send the xml above

RetornoEnvio response = (RetornoEnvio) webServiceTemplate.sendAndReceive(settings.getUrlEnviarlotes(),  
                soapActionCallback, new WebServiceMessageExtractor<Object>() {  
                    public Object extractData(WebServiceMessage response) throws IOException {  
                        Assert.isInstanceOf(SoapMessage.class, response);  
                        SoapMessage soapMessage = (SoapMessage) response;  

                        try {  

                            final StringWriter sw = new StringWriter();  

                            TransformerFactory.newInstance().newTransformer()  
                                    .transform(new DOMSource(soapMessage.getDocument()), new StreamResult(sw));  

                            JAXBContext context = JAXBContext.newInstance(RetornoEnvio.class);  

                            Unmarshaller unmarshaller = context.createUnmarshaller();  

                            XMLStreamReader xmlStreamReader = XMLInputFactory.newInstance()  
                                    .createXMLStreamReader(new StringReader(  
                                            XMLUtils.extractValueByTag(sw.toString(), "EnviarLoteEventosResult")));  

                            XMLReaderWithoutNamespace readerWithoutNamespace = new XMLReaderWithoutNamespace(  
                                    xmlStreamReader);  

                            RetornoEnvio retorno = (RetornoEnvio) unmarshaller.unmarshal(readerWithoutNamespace);  
                            retorno.setXmlEnvio(xmlEnvio);  
                            return retorno;  

                        } catch (Exception e) {  
                            throw new IOException("Error in unmarshaller xml return.", e);  
                        }  
                    }  
                });  

I don’t know where I’m going wrong, in case you need more details just talk I’ve tried almost everything and always return the same error I can access the url through the browser and the event I’m trying to send is the S1000.

3 answers

1

Communication with eSocial services should be done through the communication protocol HTTPS, using the encryption protocol TLS, and, citing the eSocial Developer’s Manual, on page 19:

The physical means of communication used will be the Internet, with the use of the protocol HTTPS (TLS) with mutual authentication, which, in addition to guaranteeing a secure communication pipeline on the Internet, allows the server and client identification through digital certificates.

This means that it is necessary to inform a valid digital certificate on the client side to establish the connection to the service, but that there is also a verification of the server certificate. The HTTP response code 403 Forbidden (Forbidden) usually indicates that there was some kind of failure with the certificates, when accessing the service.

I program mainly using the . NET Framework and I don’t know much about Java, but from what I could understand from your code it seems that the digital certificate is already being informed in the context of the connection with the service. But beyond that it is necessary to check:

  • The digital certificate used for the connection is valid?
  • It is an e-CNPJ or e-CPF certificate of the A series (A1 or A3)?

However, it is likely that the problem is in the server certificate, since the SERPRO certificate is not recognized as a reliable certificate, and so it is necessary to install on the client computer a chain of certificates provided by them (the 3 certificates below the item "Chain of Certificates issued on 02/06/2017", on this page). See more details on this in this reply:

See also item 02.01 of page Frequently Asked Questions of eSocial:

02.01 - (01/11/2018) Although all required certificates have been installed, eSocial returns error message 403. Would like information on how to access the production environment.
Guidance on the use of digital certification is given in section "4.4. Digital certificate standard" of the Developer Guidance Manual, available in the Technical Documentation. In addition, it is worth remembering that the certificates used must be in their period of validity. The user must install in its servers the chain of certificate of eSocial that is available in: https://certificados.serpro.gov.br/serproacf/certificate-chain.

1


Here’s a simple example of a Ws connection/consumption in java with certificate.

package ws_client;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class Consumindo {
    public static void main(String[] args) throws Exception {
        String url_ws = "https://www1.nfe.fazenda.gov.br/NFeDistribuicaoDFe/NFeDistribuicaoDFe.asmx?op=nfeDistDFeInteresse";
        String path_pk = "/path/to/file.pfx";
        String pass = "pk_pass";
        String soap_message = "<soap12:Envelope xmlns:soap12=\"http://www.w3.org/2003/05/soap-envelope\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"><soap12:Header><nfeCabecMsg xmlns=\"http://www.portalfiscal.inf.br/nfe/wsdl/NFeDistribuicaoDFe\"><versaoDados>1.00</versaoDados></nfeCabecMsg></soap12:Header><soap12:Body><nfeDistDFeInteresse xmlns=\"http://www.portalfiscal.inf.br/nfe/wsdl/NFeDistribuicaoDFe\"><nfeDadosMsg><distDFeInt versao=\"1.00\" xmlns=\"http://www.portalfiscal.inf.br/nfe\"><tpAmb>1</tpAmb><cUFAutor>35</cUFAutor><CNPJ>00000000000000</CNPJ><distNSU><ultNSU>000000000000001</ultNSU></distNSU></distDFeInt></nfeDadosMsg></nfeDistDFeInteresse></soap12:Body></soap12:Envelope>";
        Consumindo c  = new Consumindo();
        System.out.println(c.consome(url_ws, path_pk, pass, soap_message));

    }
    public String consome(String url_ws, String path_pk, String pass, String soap_message) throws Exception{


        // Aqui vc carrega sua chave privada
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        FileInputStream fis = new FileInputStream(new File(path_pk));
        ks.load(fis, pass.toCharArray());
        fis.close();

        URL url = new URL(url_ws);

        // Com isso não será checado de o certificado do site é válido ou não
        TrustManager[] trustAllCerts = new TrustManager[] { 
            new X509TrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
                @Override
                public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}
                @Override
                public X509Certificate[] getAcceptedIssuers() {return null;}
            }
        };

        // Aqui vc cria o gerenciador de chave que vai ser chamado mais a baixo
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init(ks, pass.toCharArray());

        // Cria-se o contexto da requisição, onde vc vai ignorar qualquer erro do certificado da URL (CA não reconhecida pelo java por exemplo)
        // e também adiciona a chave privada no contexto, necesária para consumir o ws
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(kmf.getKeyManagers(), trustAllCerts, new SecureRandom());

        // define que vc vai usar o contexto em HttpsURLConnection 
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

        HttpsURLConnection uc = (HttpsURLConnection) url.openConnection();
        // define que vai enviar dados da requisição
        uc.setDoOutput(true);
        uc.setRequestMethod("POST");
        uc.setRequestProperty("Content-Type", "text/xml; charset=UTF-8");
        OutputStream wr = uc.getOutputStream();
        wr.write(soap_message.getBytes());
        wr.flush();
        wr.close();



        BufferedReader in = new BufferedReader(new InputStreamReader(uc.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();
        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();
        return response.toString();
    }
}

To consume the WS in

https://webservices.producaorestrita.esocial.gov.br/servicos/empregador/enviarloteeventos/WsEnviarLoteEventos.svc

You need to set the url as:

String url_ws = "https://webservices.producaorestrita.esocial.gov.br/servicos/empregador/enviarloteeventos/WsEnviarLoteEventos.svc";

And you need to set a new attribute in the request header

uc.setRequestProperty("SOAPAction", "http://www.esocial.gov.br/servicos/empregador/lote/eventos/envio/v1_1_0/ServicoEnviarLoteEventos/EnviarLoteEventos");
  • What is the WS url?

  • https://webservices.producaorestrita.esocial.gov.br/servicos/empregador/enviarloteeventos/WsEnviarLoteEventos.svc

0

Follows the amendment by:

public SSLContext sslContext() throws Exception {


    KeyStore keyStore = WsUtils.loadKeyStore(resourceKeyStore.getInputStream(), resourceKeyStorePassword.toCharArray());
    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    kmf.init(keyStore, resourceKeyStorePassword.toCharArray());
    KeyManager[] kms = kmf.getKeyManagers();

    InputStream fileCacerts = WsUtils.getCacert();
    final TrustManager[] trustManagers = createTrustManagers(fileCacerts);

    SSLContext sslContext = SSLContext.getInstance(protocol);
    sslContext.init(kms, trustManagers,new SecureRandom());
    fileCacerts.close();
    return sslContext;



}

public static InputStream getCacert() throws Exception {

        char[] senha = "changeit".toCharArray();

        Path cacertPath = Paths.get(System.getProperty("java.home"), "lib", "security", "cacerts");
        Path savePath = Paths.get(CAMINHO_TEMP, "cacerts");

        File arquivoCacert = new File(cacertPath.toString());

        if (!arquivoCacert.isFile()) {

            throw new Exception("Arquivo cacerts não encontrado no JRE");
        }

        InputStream in = new FileInputStream(arquivoCacert);

        // Obtem KeyStore do Java
        KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
        ks.load(in, senha);
        in.close();

        // Adiciona caminhos das URLs ESOCIAL ao KeyStore
        get("webservices.producaorestrita.esocial.gov.br", ks);

        // Salva
        OutputStream out = new FileOutputStream(savePath.toString());
        ks.store(out, senha);
        out.close();

        InputStream retorno = new FileInputStream(savePath.toString());

        return retorno;
    }

A topic also that helped me in the implementation: https://stackoverflow.com/questions/6994944/connect-to-a-https-site-with-a-given-p12-certificate

Thank you to everyone who helped.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.