[英]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.