[英]In Groovy, how do you use a ca.pem when making a URL connection?
I have a web service I want to POST to.我有一个要发布到的 Web 服务。 With curl I can do this:
使用 curl 我可以做到这一点:
curl --cacert ~/ca.pem [...]
which works fine.这工作正常。
In Groovy I'm doing this:在 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"))
That last line fails with:最后一行失败:
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
Is there a simple way of setting my ca cert (which is a user configurable path)?有没有一种简单的方法来设置我的 ca 证书(这是一个用户可配置的路径)? That doesn't involve shelling out?
这不涉及炮轰吗?
I saw this answer: https://stackoverflow.com/a/48173910/675083 But is that relevant to me and is it really that complicated?我看到了这个答案: https : //stackoverflow.com/a/48173910/675083但这与我有关吗,真的那么复杂吗?
java works only with keystores. Java仅适用于密钥库。
and your ca.pem
I guess is a certificate. 我猜你的
ca.pem
是证书。
you have to put it into standard java ca-store located here: 您必须将其放入位于以下位置的标准java ca存储中:
$JAVA_HOME/jre/lib/security/cacerts
or you could convert your certificate into pkcs12
keystore with openssl and set it as java truststore during startup: 或者您可以使用openssl将证书转换为
pkcs12
密钥库,并在启动期间将其设置为java truststore:
java -Djavax.net.ssl.trustStore=path_to_pksc12 \
-Djavax.net.ssl.trustStorePassword=changeit \
-Djavax.net.ssl.trustStoreType=pksc12 \
...
but if you want to do it dynamically it'll be so complicated as you've found 但是如果您想动态地进行操作,就会发现它是如此复杂
I found this code that worked: 我发现此代码有效:
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());
Bit late but I was searching for something similar and I think there is a middle ground that allows you to dynamically use your ca certificate and isn't too horrible Essentially you want to trust the CA so you need to tell Groovy to trust it.有点晚了,但我正在寻找类似的东西,我认为有一个中间立场,它允许您动态使用您的 ca 证书,并且不会太可怕基本上您想要信任 CA,因此您需要告诉 Groovy 信任它。
As above java deals in keystores so your first step should be to add the pem file to a keystore如上所述,java 处理密钥库,因此您的第一步应该是将 pem 文件添加到密钥库
keytool -import -alias somealias -keystore ca.jks -file ca.pem
(this assumes your pem is a single certificate with no headers etc. but if not there are plenty of guides on how to add certificate to a keystore). (这假设您的 pem 是一个没有标题等的单个证书,但如果不是,则有很多关于如何将证书添加到密钥库的指南)。
Then you need to create an SSLContext
and load your ketystore然后你需要创建一个
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)
Then finally get your connection to use the context然后最后让您的连接使用上下文
def post = new URL("$endpoint").openConnection()
post.setSSLSocketFactory(context.socketFactory)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.