java - SSL:400 未发送所需的证书

标签 java oracle ssl

代码和输入

我正在尝试建立 SSL 连接,我收到来自服务器的 400 No required SSL certificate was sent 响应。我正在以标准方式执行此操作,例如描述的 here ;我运行 Java 8。

我的代码示例是:

    OkHttpClient client     = new OkHttpClient();
    KeyStore keyStoreClient = getClientKeyStore();
    KeyStore keyStoreServer = getServerKeyStore();
    String algorithm        = ALGO_DEFAULT;//this is defined as "PKIX"

    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
    keyManagerFactory.init(keyStoreClient, PASSWORD_SERVER.toCharArray());

    SSLContext sslContext = SSLContext.getInstance("TLS");

    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
    trustManagerFactory.init(keyStoreServer);

    sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());

    client.setSslSocketFactory(sslContext.getSocketFactory());
    client.setConnectTimeout(32, TimeUnit.SECONDS); // connect timeout
    client.setReadTimeout(32, TimeUnit.SECONDS);    // socket timeout

    return client;

这是我用来发送 GET 请求的代码:

public String get(String url) throws IOException
{
    String callUrl  = URL_LIVE.concat(url);
    Request request = new Request.Builder()
            .url(callUrl)
            .build();
    Response response = this.client.newCall(request).execute();
    return response.body().string();
}

我启用了:

System.setProperty("javax.net.debug", "ssl");

所以要查看调试消息 - 但那里没有错误/警告/警报,唯一的事情是在最后:

main, called close()
main, called closeInternal(true)
main, SEND TLSv1.2 ALERT:  warning, description = close_notify
main, WRITE: TLSv1.2 Alert, length = 26
main, called closeSocket(true)

这是我唯一可以视为“异常”的东西(但我对此表示怀疑)。

我试过了:

  • 不同的协议(protocol)禁用/启用。例如,为套接字强制使用 TLSv1/TLSv1.1 但没有成功。为了尝试,我将我的 ssl 工厂包装到另一个禁用/启用某些协议(protocol)的工厂中。
  • 禁用 SSLv2Hello - 但它不会改变画面。
  • 安装 Oracle policies因为之前有关于一些跳过算法的通知,这个安装“解决了”,但总体结果仍然相同。
  • 设置 System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true"); - 蹩脚的,但除了日志中的消息 之外也没有改变任何东西允许不安全的重新协商:true(显然是“false”)
  • 使用 KeyManagerFactory.getDefaultAlgorithm() 作为 algorithm 进行 KeyManagerFactory.getInstance() 调用。这会引发异常 Get Key failed: Given final block not properly padded 据我所知,这是因为使用了错误的算法(阅读 this )。我的默认算法是:SunX509
  • 使用 keytool -importcert -file/path/to/certificate -keystore keystore.jks -alias "Alias" 将证书直接添加到我的机器,然后通过 在我的程序中使用它System.setProperty("javax.net.ssl.trustStore","/path/to/keystore.jks"); 设置密码:System.setProperty("javax.net.ssl.trustStorePassword","mypassword");(我在 keytool 中设置了密码,然后用 yes 确认了受信任的证书);见thisthis职位。没有出现任何错误 - 但问题仍然存在。
  • 将证书添加到全局 keystore (位于 JAVA_PATH/jre/lib/security/cacerts 中的那个):keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias 别名 -file/path/to/certificate (参见 this );看起来导入操作成功,但它并没有改变图片

调试中还有一个注意事项:ssl: KeyMgr: choosing key: 1 (verified: OK) - 不确定它是否相关,因为我不是 SSL 专家。

很遗憾,我看不到服务器端日志,因此无法观察全貌。

问题

出现此 400 错误的原因是什么?我该如何进一步推进(调试/尝试其他操作)?任何提示将不胜感激。

最佳答案

您的服务器正在请求客户端证书。您需要在客户端计算机上安装证书(由受信任的机构签名),并让您的程序知道它。

通常,您的服务器有一个证书( key 用途设置为“TLS 服务器身份验证”),由您组织的 IT 安全部门或某些全局信任的 CA 签名。您应该从同一来源获得用于“TLS 客户端身份验证”的证书。

如果您在 Wireshark 中捕获 TLS 握手,您将看到 ServerHello 消息后跟“客户端证书请求”,您会使用长度为 0 的“客户端证书”消息回复该消息。您的服务器选择拒绝此请求。

关于java - SSL:400 未发送所需的证书,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36284543/

相关文章:

java - Java中使用%n或\n格式化字符串

java - 在 oracle Spring/JPA 中对分组行本身进行排序

java - java中的Oracle连接(错误是无效的列名)

如果我从 wi-fi 切换到 3g,ios https 会失败

ssl - 将自签名证书与 keytool 一起用于开发目的

java - 取消请求时取消 REST 服务

java - 如何在我的自定义 osmdroid map 上设置拖动开始和结束监听器?

java - 在Neo4j中,使用Java API时有什么方法可以限制路径中的节点和关系类型吗?

oracle - ORA-01840 : input value not long enough for date format when executing a query with a timestamp parameter

java - 在改造库中禁用 SSL 证书检查