如何将Java客户端连接到Windows 10上的Azure Cosmos数据库模拟器,找不到证书

2022-02-27 00:00:00 azure client keystore java

问题:我的演示代码客户端无法连接到Windows 10上的Azure Cosmos模拟器。

步骤:

  1. 我在Windows上安装了Cosmosdb模拟器-看起来不错

  2. 根据文档,我启动了Windows cert manage.msc。我选择友好名称为";DocumentDBEmulatorCertificate";的私有证书作为本地磁盘的base64编码的x.509.cer文件

  3. 我以管理员身份启动了Windows中的cmd控制台,并将cmd控制台cd转到本地JAVA_HOME/lib/security目录(我使用的是Java 8.0.131)

  4. 我使用此命令运行了keytool

    keytool-import-trustcacerts-keystore cacerts-store pass changeit-nopt-alias azureCosmossDBEmulator-FILE";D:导出的certificatescosmossDB-emulator-cert.cer";

  5. 我将修改后的密钥库列出为dump.txt文件。我可以在转储中看到我的条目

    azurecosmossdbmulator,2017年8月30日,trustedCertEntry, 证书指纹(Sha1):5B:F4:14:BE:9F:2B:7F:6A:2B:C0:87:A4:3E:4D:9A:52:45:FA:2F:EA

    并且这与X.509证书中的指纹值匹配。

  6. 我在生成时重新启动了IntelliJ,并检查Java 8.0.1.3.1是项目中唯一的JDK。

  7. 我在调试中启动了Groovy测试脚本,并逐步执行代码。我可以创建DocumentClient OK。

  8. 这只是测试连接代码的粗略脚本,如下所示

     final String key = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw=="
    
     DocumentClient client = new DocumentClient("https://localhost:8081", key
                 , new ConnectionPolicy(), ConsistencyLevel.Session)
    
     String dbname = "familyDB"
         String dblink = "/dbs/$dbname"
    
     //create db if not exists
     try {
         client.readDatabase(dblink,null)
         println "found db $dbname"
     } catch (DocumentClientException de) {
         if (de.getStatusCode() == 404) {
             Database db = new Database()
             db.id = dbname
             client.createDatabase(db, null)
             println "created new DB $dbname"
     } else {
         throw de
     }
     }
    

当我到达client.readDatabase行时,我收到如下异常:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Caught: java.lang.IllegalStateException: Http client execution failed.
java.lang.IllegalStateException: Http client execution failed.
    at com.microsoft.azure.documentdb.internal.GatewayProxy.performGetRequest(GatewayProxy.java:234)
    at com.microsoft.azure.documentdb.internal.GatewayProxy.doRead(GatewayProxy.java:89)
    at com.microsoft.azure.documentdb.internal.GatewayProxy.processMessage(GatewayProxy.java:336)
    at com.microsoft.azure.documentdb.DocumentClient$8.apply(DocumentClient.java:2985)
    at com.microsoft.azure.documentdb.internal.RetryUtility.executeDocumentClientRequest(RetryUtility.java:58)
    at com.microsoft.azure.documentdb.DocumentClient.doRead(DocumentClient.java:2991)
    at com.microsoft.azure.documentdb.DocumentClient.readDatabase(DocumentClient.java:491)
    at com.microsoft.azure.documentdb.DocumentClient$readDatabase.call(Unknown Source)
    at com.softwood.azure.client.cosmossDBClientScript.run(cosmossDBClientScript.groovy:29)
Caused by: 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
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:394)
    at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:353)
    at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:141)
    at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:353)
    at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:380)
    at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236)
    at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:184)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:107)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:55)
    at com.microsoft.azure.documentdb.internal.GatewayProxy.performGetRequest(GatewayProxy.java:231)
    ... 8 more
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    ... 20 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    ... 20 more

这基本上说明它找不到我的cacert条目并拒绝连接。

出了什么问题?(我还没有重新启动Windows)。证书看起来没问题,似乎可以通过keytool导入cacerts,我使用的是单个JDK引用,但代码无法连接。

我如何才能解开我没有正确完成的、现在必须执行的操作才能使代码从Java连接到在Windows 10计算机上本地运行的Azure DB模拟器?


解决方案

根据您的描述,我还使用Document DB JavaSDK编写了一段代码连接到Cosmos DB仿真器,结果遇到了与您相同的问题。

package emulator;

import com.microsoft.azure.documentdb.ConnectionPolicy;
import com.microsoft.azure.documentdb.ConsistencyLevel;
import com.microsoft.azure.documentdb.Database;
import com.microsoft.azure.documentdb.DocumentClient;
import com.microsoft.azure.documentdb.DocumentClientException;

public class TestEmlulator {

    // Replace with your DocumentDB end point and master key.
    private static final String END_POINT = "https://localhost:8081/";
    private static final String MASTER_KEY = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==";

    public static void main(String[] args) throws DocumentClientException {
        // Connect to the Azure Cosmos DB Emulator running locally
        DocumentClient client = new DocumentClient(END_POINT, MASTER_KEY, ConnectionPolicy.GetDefault(),
                ConsistencyLevel.Session);

        Database database = new Database();
        database.setId("testEmulator");
        database = client.createDatabase(database, null).getResource();

        System.out.println(database.toJson());
    }

}

所以我导出cosmosDB的证书,将其命名为documentdbemulatorcert.cer,并按照official tutorial提供的方式存储在我的D盘中。您似乎也做了同样的事情。

然后,我尝试将cosmosdb的证书导入到JVM信任证书列表中。您也可以参考下面的步骤:

步骤1:打开CMD命令窗口,进入%JAVA_HOME%/jre/lib/security目录。请注意,必须使用administrator privileges

打开命令窗口

对我来说,目录看起来像C:Program FilesJavajdk1.8.0_131jrelibsecurity

步骤2:在打开的命令窗口中,输入以下命令:

keytool -import -alias cacerts -keystore cacerts -file d:documentdbemulatorcert.cer

输入默认密码:changeit,然后在Trust this certificate? [no]:

旁边输入Y或y

第3步:您可以看到Certificate was added to keystore证书是否已成功导入。

您可以参考下面的截图了解整个过程:

最后,我的代码可以工作了!

您也可以参考下面的SO线程:

1.Unable to find valid certification path to requested target - error even after cert imported

2."PKIX path building failed" and "unable to find valid certification path to requested target"

希望它能帮助您。

相关文章