Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/362.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java SSL:400未发送所需的证书_Java_Oracle_Ssl - Fatal编程技术网

Java SSL:400未发送所需的证书

Java SSL:400未发送所需的证书,java,oracle,ssl,Java,Oracle,Ssl,代码和输入 我正在尝试建立SSL连接,并且从服务器收到400未发送所需SSL证书的响应。我用一种标准的方式来做这件事,就像上面描述的那样;我运行Java8 我的代码示例如下: OkHttpClient client = new OkHttpClient(); KeyStore keyStoreClient = getClientKeyStore(); KeyStore keyStoreServer = getServerKeyStore(); String

代码和输入

我正在尝试建立SSL连接,并且从服务器收到
400未发送所需SSL证书的
响应。我用一种标准的方式来做这件事,就像上面描述的那样;我运行Java8

我的代码示例如下:

    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)
这是我唯一可以视为“不正常”的东西(但我怀疑这是真的)

我试过:

  • 不同的协议禁用/启用。例如,对套接字强制执行
    TLSv1
    /
    TLSv1.1
    ,但没有成功。为了尝试这一点,我将我的ssl工厂包装到另一个禁用/启用某些协议的工厂中
  • 禁用
    SSLv2Hello
    ——但不会改变画面
  • 安装是因为之前有一些关于跳过的算法的通知,这次安装“解决”了这个问题,但总体结果仍然是一样的
  • 设置
    System.setProperty(“sun.security.ssl.allowUnsafeRenegotiation”,“true”)-蹩脚,但除了日志中的消息之外,也没有更改任何内容
    允许不安全的重新协商:true
    (显然是“false”)
  • 使用
    KeyManagerFactory.getDefaultAlgorithm()
    作为
    KeyManagerFactory.getInstance()调用的
    algorithm
    。这引发了异常
    Get Key失败:给定的最后一个块没有正确填充
    ,据我所知,这是因为使用了错误的算法(读取)。我的默认算法是:
    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
    确认了可信证书);见和帖子。此问题未引发任何错误,但问题仍然存在
  • 使用:
    keytool-import-trustcacerts-keystore-cacerts-storepass changeit-noprompt-alias alias-file/PATH/to/certificate
    将证书添加到全局密钥库(位于
    JAVA_PATH/jre/lib/security/cacerts
    中);看起来导入操作已成功,但未更改图片
调试中还有一个注意事项:
ssl:KeyMgr:choosing key:1(verified:OK)
-不确定它是否相关,因为我不是ssl专家

不幸的是,我看不到服务器端日志,因此无法观察完整的情况

问题


这400错误的原因是什么?我如何进一步(调试/尝试其他方法)?任何提示都将不胜感激。

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

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


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

我有一个证书,我有:
keytool-importcert-file/path/here-keystore keystore.jks-alias“alias”
,然后设置密码。在我的程序中,我做了:
System.setProperty(“javax.net.ssl.trustStore”,“/path/to/jks”)
System.setProperty(“javax.net.ssl.trustStorePassword”、“password”)但我仍然有同样的问题。我做的对吗?从尝试,您没有客户端证书,除非您已创建(1)密钥对和(2)自签名证书或(3)CSR和(4)由CA签名,并且这些操作都无法在JDK的信任库中有效执行。我有pkcs12格式的客户端证书。我尝试导出它,但实际上成功地使用了
keytool-importkeystore-destkeystore-srckeystore cert-srcstoretype PKCS12-srcstorepass certPass-alias 1
,我知道
certPass
是有效的,因为我能够用它解锁PKCS12证书,并在其中看到证书+私钥。我发现了问题。就像@EJP说的,自签名证书。我现在已经修复了所有问题。