调用具有私有证书的内部API
了解如何使用专用证书或自签名证书从AEM向Web API进行HTTPS调用。
默认情况下,在尝试与使用自签名证书的Web API建立HTTPS连接时,连接会失败,并出现以下错误:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
当 API的SSL证书未由可识别的证书颁发机构(CA) 颁发且Java™应用程序无法验证SSL/TLS证书时,通常会发生此问题。
让我们了解如何使用Apache HttpClient和 AEM的全局TrustStore 成功调用具有私有证书或自签名证书的API。
使用HttpClient的典型API调用代码
以下代码创建到Web API的HTTPS连接:
...
String API_ENDPOINT = "https://example.com";
// Create HttpClientBuilder
HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
// Create HttpClient
CloseableHttpClient httpClient = httpClientBuilder.build();
// Invoke API
CloseableHttpResponse closeableHttpResponse = httpClient.execute(new HttpGet(API_ENDPOINT));
// Code that reads response code and body from the 'closeableHttpResponse' object
...
该代码使用Apache HttpComponent的HttpClient库类及其方法。
HttpClient和加载AEM TrustStore资料
要调用具有 私有或自签名证书 的API终结点,HttpClient的SSLContextBuilder
必须使用AEM的TrustStore加载,并且用于促进连接。
请按照以下步骤操作:
-
以 管理员 的身份登录到 AEM作者。
-
导航到 AEM Author > Tools > Security > Trust Store,然后打开 全局信任存储。 如果首次访问,请为全局信任存储区设置密码。
-
要导入专用证书,请单击 选择证书文件 按钮,然后选择所需的扩展名为
.cer
的证书文件。 通过单击 提交 按钮导入它。 -
更新Java™代码,如下所示。 请注意,要使用
@Reference
获取AEMKeyStoreService
,调用代码必须是OSGi组件/服务或Sling模型(并在其中使用@OsgiService
)。code language-java ... // Get AEM's KeyStoreService reference @Reference private com.adobe.granite.keystore.KeyStoreService keyStoreService; ... // Get AEM TrustStore using KeyStoreService KeyStore aemTrustStore = getAEMTrustStore(keyStoreService, resourceResolver); if (aemTrustStore != null) { // Create SSL Context SSLContextBuilder sslbuilder = new SSLContextBuilder(); // Load AEM TrustStore material into above SSL Context sslbuilder.loadTrustMaterial(aemTrustStore, null); // Create SSL Connection Socket using above SSL Context SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory( sslbuilder.build(), NoopHostnameVerifier.INSTANCE); // Create HttpClientBuilder HttpClientBuilder httpClientBuilder = HttpClientBuilder.create(); httpClientBuilder.setSSLSocketFactory(sslsf); // Create HttpClient CloseableHttpClient httpClient = httpClientBuilder.build(); // Invoke API closeableHttpResponse = httpClient.execute(new HttpGet(API_ENDPOINT)); // Code that reads response code and body from the 'closeableHttpResponse' object ... } /** * * Returns the global AEM TrustStore * * @param keyStoreService OOTB OSGi service that makes AEM based KeyStore * operations easy. * @param resourceResolver * @return */ private KeyStore getAEMTrustStore(KeyStoreService keyStoreService, ResourceResolver resourceResolver) { // get AEM TrustStore from the KeyStoreService and ResourceResolver KeyStore aemTrustStore = keyStoreService.getTrustStore(resourceResolver); return aemTrustStore; } ...
- 将OOTB
com.adobe.granite.keystore.KeyStoreService
OSGi服务注入您的OSGi组件。 - 使用
KeyStoreService
和ResourceResolver
获取全局AEM TrustStore,getAEMTrustStore(...)
方法可做到这一点。 - 创建
SSLContextBuilder
的对象,请参阅Java™ API详细信息。 - 使用
loadTrustMaterial(KeyStore truststore,TrustStrategy trustStrategy)
方法将全局AEM TrustStore加载到SSLContextBuilder
中。 - 通过上述方法中的
TrustStrategy
的null
,它可确保在API执行期间只有AEM信任证书能够成功。
- 将OOTB
避免JVM密钥库更改
使用私有证书有效调用内部API的传统方法涉及修改JVM密钥库。 这是通过使用Java™ keytool命令导入私有证书来实现的。
但是,此方法不符合安全最佳实践,AEM通过利用 全局信任存储区 和KeyStoreService提供了优异的选项。
解决方案包
可从此处下载视频中降级的Node.js示例项目。
AEM servlet代码在WKND站点项目的tutorial/web-api-invocation
分支中可用,请参见。