使用函数计算运行程序时候,往外调一个https的WSDL报错,请问有处理案例吗?It failed with: \n\tPKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target.
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在使用阿里云函数计算运行程序时,如果调用一个HTTPS的WSDL接口报错,错误信息为:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
这通常是由于目标服务器的SSL证书未被Java的信任库(TrustStore)识别导致的。以下是针对该问题的详细解决方案:
该错误表明Java运行时无法验证目标HTTPS服务的SSL证书链。可能的原因包括: 1. 目标服务器使用了自签名证书或非受信任的CA签发的证书。 2. 函数计算环境中的默认信任库未包含目标服务器证书的根CA。
获取目标服务器的SSL证书
使用以下命令从目标服务器导出SSL证书:
openssl s_client -connect <目标服务器域名>:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM > server-cert.pem
将<目标服务器域名>
替换为实际的目标服务器域名。
上传证书到函数计算代码包
将导出的server-cert.pem
文件与您的函数代码一起打包上传。
修改代码以加载自定义证书
在代码中指定信任库,加载自定义证书。例如,使用Java语言时,可以通过以下方式实现:
import javax.net.ssl.*;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;
public class CustomTrustManager {
public static void main(String[] args) throws Exception {
// 加载自定义证书
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream certInputStream = CustomTrustManager.class.getResourceAsStream("/server-cert.pem");
java.security.cert.X509Certificate caCert = (java.security.cert.X509Certificate) cf.generateCertificate(certInputStream);
// 创建KeyStore并加载证书
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(null, null);
keyStore.setCertificateEntry("caCert", caCert);
// 初始化TrustManagerFactory
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keyStore);
// 配置SSLContext
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(null, tmf.getTrustManagers(), null);
// 设置全局默认SSLContext
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
// 测试调用HTTPS接口
URL url = new URL("https://<目标服务器域名>/wsdl");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("GET");
System.out.println("Response Code: " + conn.getResponseCode());
}
}
重新部署函数
将修改后的代码和证书文件重新打包并部署到函数计算。
如果目标服务器的证书无法获取或您仅需临时测试,可以通过禁用SSL证书验证来绕过此问题。但请注意,这种方式存在安全风险,不建议在生产环境中使用。
以下是一个示例代码,展示如何禁用SSL证书验证:
import javax.net.ssl.*;
import java.security.cert.X509Certificate;
public class DisableSSLValidation {
public static void main(String[] args) throws Exception {
// 创建一个信任所有证书的TrustManager
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {}
public void checkServerTrusted(X509Certificate[] certs, String authType) {}
}
};
// 初始化SSLContext
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
// 设置全局默认SSLContext
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// 禁用主机名验证
HttpsURLConnection.setDefaultHostnameVerifier((hostname, session) -> true);
// 测试调用HTTPS接口
URL url = new URL("https://<目标服务器域名>/wsdl");
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("GET");
System.out.println("Response Code: " + conn.getResponseCode());
}
}
如果您无法直接解决证书问题,可以考虑使用阿里云API网关作为代理。API网关支持配置SSL证书,并可以将请求转发到目标HTTPS服务。具体步骤如下: 1. 在API网关中创建一个后端服务,指向目标HTTPS服务。 2. 配置API网关的SSL证书,确保其信任目标服务器的证书。 3. 修改函数代码,将请求发送到API网关的地址,而不是直接访问目标HTTPS服务。
通过上述方法,您可以有效解决函数计算调用HTTPS WSDL接口时的证书验证问题。如果仍有疑问,请提供更多上下文信息以便进一步分析。您可以复制页面截图提供更多信息,我可以进一步帮您分析问题原因。
你好,我是AI助理
可以解答问题、推荐解决方案等