简体   繁体   English

使用 Axis2/Java 创建 SSL 客户端

[英]Creating SSL client with Axis2/Java

I'm trying to connect to the WebService that uses SSL but no success.我正在尝试连接到使用 SSL 但没有成功的 WebService。 I use Axis2, I found some usefull article: http://people.apache.org/~dumindu/docs/HowToConfigureSSL.html , but it is for C. I use Axis2, I found some usefull article: http://people.apache.org/~dumindu/docs/HowToConfigureSSL.html , but it is for C. In this article they set pathes to SERVER_CERT, KEY_FILE and SSL_PASSPHRASE using axis2.xml or C coding.在本文中,他们使用 axis2.xml 或 C 编码设置了 SERVER_CERT、KEY_FILE 和 SSL_PASSPHRASE 的路径。 I tried to change configuration file but this doesn't work for me.我试图更改配置文件,但这对我不起作用。 If somebody know how to set this parameters from within Java code, let me know.如果有人知道如何从 Java 代码中设置此参数,请告诉我。

You may be interested in this answer to a similar question.您可能对类似问题的答案感兴趣。 In particular, Axis 2 seems to be using Apache HttpClient 3.x, according to this document :特别是,Axis 2 似乎正在使用 Apache HttpClient 3.x,根据此文档

If you want to perform SSL client authentication (2-way SSL), you may use the Protocol.registerProtocol feature of HttpClient.如果要进行 SSL 客户端认证(2-way SSL),可以使用 HttpClient 的 Protocol.registerProtocol 特性。 You can overwrite the "https" protocol, or use a different protocol for your SSL client authentication communications if you don't want to mess with regular https.如果您不想弄乱常规的 https,您可以覆盖“https”协议,或者为您的 SSL 客户端身份验证通信使用不同的协议。 Find more information at http://jakarta.apache.org/commons/httpclient/sslguide.html更多信息请访问http://jakarta.apache.org/commons/httpclient/sslguide.html

(You can build your SSLContext from your existing keystore, and configure HttpClient 3.1 using this socket factory .) (您可以从现有的密钥库构建 SSLContext,并使用 此套接字工厂配置 HttpClient 3.1。)

I initialized EasySSLProtocolSocketFactory and Protocol instances for different endpoints and register the protocol with unique key like this:我为不同的端点初始化了 EasySSLProtocolSocketFactory和 Protocol 实例,并使用这样的唯一键注册协议:

/**
 * This method does the following:
 * 1. Creates a new and unique protocol for each SSL URL that is secured by client certificate
 * 2. Bind keyStore related information to this protocol
 * 3. Registers it with HTTP Protocol object 
 * 4. Stores the local reference for this custom protocol for use during furture collect calls
 * 
 *  @throws Exception
 */
public void registerProtocolCertificate() throws Exception {
    EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory();
    easySSLPSFactory.setKeyMaterial(createKeyMaterial());
    myProtocolPrefix = (HTTPS_PROTOCOL + uniqueCounter.incrementAndGet());
    Protocol httpsProtocol = new Protocol(myProtocolPrefix,(ProtocolSocketFactory) easySSLPSFactory, port);
    Protocol.registerProtocol(myProtocolPrefix, httpsProtocol);
    log.trace("Protocol [ "+myProtocolPrefix+" ] registered for the first time");
}

/**
 * Load keystore for CLIENT-CERT protected endpoints
 */
private KeyMaterial createKeyMaterial() throws GeneralSecurityException, Exception  {
    KeyMaterial km = null;
    char[] password = keyStorePassphrase.toCharArray();
    File f = new File(keyStoreLocation);
    if (f.exists()) {
        try {
            km = new KeyMaterial(keyStoreLocation, password);
            log.trace("Keystore location is: " + keyStoreLocation + "");
        } catch (GeneralSecurityException gse) {
            if (logErrors){
                log.error("Exception occured while loading keystore from the following location: "+keyStoreLocation, gse);
                throw gse;
            }
        }
    } else {
        log.error("Unable to load Keystore from the following location: " + keyStoreLocation );
        throw new CollectorInitException("Unable to load Keystore from the following location: " + keyStoreLocation);
    }
    return km;
}   

When I have to invoke the web service, I do this (which basically replace "https" in the URL with https1, or https2 or something else depending on the Protocol you initialized for that particular endpoint):当我必须调用 web 服务时,我会这样做(基本上将 URL 中的“https”替换为 https1、https2 或其他内容,具体取决于您为该特定端点初始化的协议):

httpClient.getHostConfiguration().setHost(host, port,Protocol.getProtocol(myProtocolPrefix));
initializeHttpMethod(this.url.toString().replace(HTTPS_PROTOCOL, myProtocolPrefix));

It works like a charm!它就像一个魅力!

Ok so it's >10 years later, but anyways.好的,这是> 10年后,但无论如何。 This could have saved me some time today:)这本可以为我节省一些今天的时间:)

Create a custom HttpClient with SSLContext:使用 SSLContext 创建自定义 HttpClient:

 public static HttpClient sslEnabledHttpClient(final URL ks, final char[] storePass,
                                                  final URL ts, final char[] tsPass) {

        try {
            //Minimalistic SSLContext.
            final SSLContextBuilder builder = SSLContexts.custom()
                    .loadKeyMaterial(ks, storePass, storePass); 

            if (ts != null) {
                builder.loadTrustMaterial(ts, tsPass);
            }
            final SSLContext sslContext = builder.build();
            return HttpClientBuilder.create().setSSLContext(sslContext).build();
        } catch (final Exception e) {
            throw new RuntimeException(e);
        }
    }

And use that:并使用它:

// Out of the box Axis2 does not support SSL with client authentication.
// So we need a custom HttpClient.
final HttpClient client = Util.sslEnabledHttpClient(
        this.keyStoreURL, this.keyStorePassword.toCharArray(),
        this.trustStoreURL, this.trustStorePassword.toCharArray());


myStub._getServiceClient().getOptions().setProperty(HTTPConstants.CACHED_HTTP_CLIENT, client);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM