繁体   English   中英

在 Groovy 中,如何在进行 URL 连接时使用 ca.pem?

[英]In Groovy, how do you use a ca.pem when making a URL connection?

我有一个要发布到的 Web 服务。 使用 curl 我可以做到这一点:

curl --cacert ~/ca.pem [...]

这工作正常。

在 Groovy 中,我这样做:

def post = new URL("$endpoint").openConnection()
post.setRequestMethod("POST")
post.setDoOutput(true)
post.setRequestProperty("Content-Type", "application/json")
post.setRequestProperty("Authorization", "Bearer $token")
post.getOutputStream().write(json.getBytes("UTF-8"))

最后一行失败:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

有没有一种简单的方法来设置我的 ca 证书(这是一个用户可配置的路径)? 这不涉及炮轰吗?

我看到了这个答案: https : //stackoverflow.com/a/48173910/675083但这与我有关吗,真的那么复杂吗?

Java仅适用于密钥库。

我猜你的ca.pem是证书。

您必须将其放入位于以下位置的标准java ca存储中:

$JAVA_HOME/jre/lib/security/cacerts 

或者您可以使用openssl将证书转换为pkcs12密钥库,并在启动期间将其设置为java truststore:

java -Djavax.net.ssl.trustStore=path_to_pksc12 \
  -Djavax.net.ssl.trustStorePassword=changeit \
  -Djavax.net.ssl.trustStoreType=pksc12 \
  ...

但是如果您想动态地进行操作,就会发现它是如此复杂

我发现此代码有效:

def nullHostnameVerifier = [
            verify: { hostname, session -> true }
        ]
        HttpsURLConnection.setDefaultHostnameVerifier(nullHostnameVerifier as HostnameVerifier)

        def is = new File(cacertPath).newInputStream() // *** how to close?

        TrustManager[] trustManagers = null;
        char[] password = null; // Any password will work.
        KeyStore caKeyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        caKeyStore.load(null, password);
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(is);
        if (certificates.isEmpty()) {
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");
        }
        int index = 0;
        certificates.each {
            String certificateAlias = "ca" + Integer.toString(index++);
            caKeyStore.setCertificateEntry(certificateAlias, it);
        }
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(caKeyStore);
        trustManagers = trustManagerFactory.getTrustManagers();

        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trustManagers, new SecureRandom());
        HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());

有点晚了,但我正在寻找类似的东西,我认为有一个中间立场,它允许您动态使用您的 ca 证书,并且不会太可怕基本上您想要信任 CA,因此您需要告诉 Groovy 信任它。

如上所述,java 处理密钥库,因此您的第一步应该是将 pem 文件添加到密钥库

keytool -import -alias somealias -keystore ca.jks -file ca.pem

(这假设您的 pem 是一个没有标题等的单个证书,但如果不是,则有很多关于如何将证书添加到密钥库的指南)。

然后你需要创建一个SSLContext并加载你的ketystore

import javax.net.ssl.SSLContext
import javax.net.ssl.TrustManagerFactory
import java.security.KeyStore

def context = SSLContext.getInstance('SSL')
def tks = KeyStore.getInstance(KeyStore.defaultType);
def tmf = TrustManagerFactory.getInstance('SunX509')

new File ("/path/to/ca.jks").withInputStream { stream ->
  tks.load(stream, "password".toCharArray())
}
tmf.init(tks)
context.init(null, tmf.trustManagers, null)

然后最后让您的连接使用上下文

def post = new URL("$endpoint").openConnection()
post.setSSLSocketFactory(context.socketFactory)

暂无
暂无

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

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