membrane / soa-model

Toolkit and Java API for WSDL, WADL and XML Schema.
http://www.membrane-soa.org/soa-model/
Apache License 2.0
93 stars 73 forks source link

The framework does not make http request with ssl (using an electronic certificate) to connect to url and get service contract (WSDL). #232

Open gustavoaalves opened 9 years ago

gustavoaalves commented 9 years ago

This need to do this to use the framework of you and generate sample request envelope on the web services of the Secretariats of the Brazilian Finance (SEFAZ - Invoice Project).

I am using a smartcard. For my case quickly made some changes just to better show my need.

Functions ExternalResolver.groovy:

private resolveAsString(url) { try{ HttpResponse con = requestSSL(url) EntityUtils.toString(con.entity) } catch (ResourceDownloadException e) { throw e } catch (Exception e) { throw new ResourceDownloadException(rootCause : e.getCause(), url : url) } }

private request(url) {
    HttpClient client = new DefaultHttpClient();
    if ( proxyHost ) {
        HttpHost proxy = new HttpHost(proxyHost, proxyPort);
        client.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
    }

    HttpParams params = client.getParams();
    HttpConnectionParams.setConnectionTimeout(params, timeout);

    HttpGet method = new HttpGet(url);
    method.setHeader("User-Agent", "SOA Model (see http://membrane-soa.org)")
    HttpResponse response = client.execute(method)
    if(response.statusLine.statusCode != 200) {
        def rde = new ResourceDownloadException("could not get resource $url by HTTP")
        rde.status = status
        rde.url = url
        method.releaseConnection()
        throw rde
    }
    response
}

private requestSSL(url) {
    def client = new ClientSSL(url)
    HttpResponse response = client.getResponse();
    response
}

ClientSSL.java:

package com.predic8.xml.util;

import java.io.ByteArrayInputStream; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.Socket; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.Principal; import java.security.PrivateKey; import java.security.Provider; import java.security.Security; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.util.Enumeration;

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 javax.net.ssl.X509TrustManager;

import org.apache.http.HttpResponse; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams;

public class ClientSSL {

HttpResponse response;
String pathCacerts = "C:\\Temp\\";
String fileCacerts = "nfe-cacerts";

public ClientSSL(String url) throws Exception {

    final NFeBuildCacerts cacerts = new NFeBuildCacerts("C:\\Temp\\", url);
    // TODO Auto-generated constructor stub
    HttpClient httpclient = new DefaultHttpClient();
    KeyStore trustStore;
    try {
        String alias = "";
        Provider provider = new sun.security.pkcs11.SunPKCS11(this.leitorGemPC_Perto());
        Security.addProvider(provider);
        trustStore = KeyStore.getInstance("pkcs11");
        String pin = new String("your_pass");
        trustStore.load(null, pin.toCharArray());

        final Enumeration<String> aliasesEnum = trustStore.aliases();
        while (aliasesEnum.hasMoreElements()) {
            alias = aliasesEnum.nextElement();
            if (trustStore.isKeyEntry(alias)) {
                break;
            }
        }

        X509Certificate certificate = (X509Certificate) trustStore.getCertificate(alias);
        PrivateKey privateKey = (PrivateKey) trustStore.getKey(alias, pin.toCharArray());

        final KeyManager[] keyManagers = this.createKeyManagers(certificate, privateKey);
        final TrustManager[] trustManagers = this.createTrustManagers();
        final SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(keyManagers, trustManagers, null);          
        SSLSocketFactory ssf = new SSLSocketFactory(sslContext,SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

        //SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
        Scheme sch = new Scheme("https", 443, ssf);
        httpclient.getConnectionManager().getSchemeRegistry().register(sch);
        HttpParams params = httpclient.getParams();
        HttpConnectionParams.setConnectionTimeout(params, 10000);

        HttpGet method = new HttpGet(url);
        method.setHeader("User-Agent", "SOA Model (see http://membrane-soa.org)");
        HttpResponse response = httpclient.execute(method);
        if(response.getStatusLine().getStatusCode() != 200) {
            ResourceDownloadException rde = new ResourceDownloadException("could not get resource by HTTP");
            method.releaseConnection();
        }
        this.setResponse(response);
    } catch (KeyStoreException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (CertificateException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (KeyManagementException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (UnrecoverableKeyException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public KeyManager[] createKeyManagers(X509Certificate certificate, PrivateKey privateKey) {
    final HSKeyManager keyManager = new HSKeyManager(certificate, privateKey);
    return new KeyManager[]{keyManager};
}

public TrustManager[] createTrustManagers() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
    final KeyStore trustStore = KeyStore.getInstance("JKS");
    trustStore.load(new FileInputStream(this.pathCacerts + this.fileCacerts), "changeit".toCharArray());
    final TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(trustStore);
    return trustManagerFactory.getTrustManagers();
}

public HttpResponse getResponse() {
    return response;
}

public void setResponse(HttpResponse response) {
    this.response = response;
}

public InputStream leitorGemPC_Perto() throws UnsupportedEncodingException {
    return this.defaultConfig("SmartCard", "c:/windows/system32/aetpkss1.dll");
}
private InputStream defaultConfig(final String name, final String library) throws UnsupportedEncodingException {
    final StringBuilder conf = new StringBuilder();
    conf.append("name = ").append(name).append("\n\r").append("library = ").append(library).append("\n\r").append("showInfo = true");
    return new ByteArrayInputStream(conf.toString().getBytes("UTF-8"));
}

class HSKeyManager implements X509KeyManager {

    private final X509Certificate certificate;
    private final PrivateKey privateKey;

    public HSKeyManager(final X509Certificate certificate, final PrivateKey privateKey) {
        this.certificate = certificate;
        this.privateKey = privateKey;
    }

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

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

    public X509Certificate[] getCertificateChain(final String arg0) {
        return new X509Certificate[]{this.certificate};
    }

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

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

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

}

NFeBuildCacerts.java:

/**

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;

/**

}

gustavoaalves commented 9 years ago

No return?

rrayst commented 9 years ago

@gustavoaalves, what is the question? ;)

gustavoaalves commented 9 years ago

My need is to make a secure HTTP request using a digital certificate to capture the wsdl. The code that I put up, only reports exactly what the problem is and what the need. There is no way that I could contribute with you to add this possibility (secure HTTP request using digital certificates)? Or do you have any plans to implement something related?

predic8 commented 9 years ago

Hi, I think you did a great job with the class above. You can clone the repository here on github, make your extension and generate a pull request. Then we can incorporate this into the next release.

gustavoaalves commented 9 years ago

Okay. I'm going to pull request on this... Thanks!!