Soap Request 403 forbidden [closed]

Closed. this question is out of scope and is not currently accepting answers.

want to improve this question? Update the question so it's on-topic for Stack Overflow.

Closed 4 months ago .

improve this question

Hello guys for kindness I need your help.

I am trying to send make the connection to the esocial api but I have the return 403 forbidden, I am with certificate updated and using jks. Below follows the excerpt 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 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 I need more details just talk I've tried almost everything and always return the same error I can access the url from the browser and the event I'm trying to send is S1000.

Author: Mateus Vinicius, 2019-08-15

3 answers

Follows a simple example of connecting/consuming a ws 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

Need to set the url as:

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

And 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");
 1
Author: thiaguerd, 2019-08-19 20:28:06

Communication with eSocial services should be done through the communication protocol HTTPS , using the encryption protocol TLS , and, citing the eSocial developer 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 ensuring a secure communication pipeline on the Internet, allows identification of the server and client through digital certificates .

Which means that a valid client-side digital certificate is required to establish the connection to the service, but that there is also a server certificate verification. The HTTP response code403 Forbidden (prohibited ) usually indicates that there was some kind of certificate failure when accessing the service.

I program mainly using the .NET Framework and I do not understand much of Java, but from what I could understand from your code it seems to me that the digital certificate is already being informed in the context of the connection to the service. But besides that it is necessary to check:

  • is the digital certificate used for the connection within validity?
  • is he a series A (A1 or A3) e-CNPJ or e-CPF certificate?

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

See also item 02.01 of page of eSocial frequently asked questions:

02.01 - (11/01/2018) although all required certificates are installed, eSocial returns error message 403. I would like information on how to access the production environment.
guidance on the use of digital certification can be found in Section " 4.4. Digital certificate standard " from the developer guidance Manual, available in the area of Technical Documentation . In addition, it is worth remembering that the certificates used must be expired. The user must install on their servers the esocial certificate string which is available at: https://certificados.serpro.gov.br/serproacf/certificate-chain.

 1
Author: Pedro Gaspar, 2019-08-16 20:04:43

Follows the change:

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.

 0
Author: Mateus Vinicius, 2019-08-20 14:47:26