如何使用自签名证书从 Javascript 连接到 SSL 服务器?

Posted

技术标签:

【中文标题】如何使用自签名证书从 Javascript 连接到 SSL 服务器?【英文标题】:How to connect to SSL Server from Javascript, using self-signed certificates? 【发布时间】:2016-01-26 20:16:19 【问题描述】:

我创建了一个简单的示例来说明我正在尝试做的事情。

我有这样的服务器代码:

package com.company;

import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSocket;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;

public class EchoServer 
    public
    static
    void
    main(String[] arstring) 
        try 

            SSLServerSocketFactory sslserversocketfactory =
                    (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
            SSLServerSocket sslserversocket =
                    (SSLServerSocket) sslserversocketfactory.createServerSocket(9999);
            SSLSocket sslsocket = (SSLSocket) sslserversocket.accept();

            InputStream inputstream = sslsocket.getInputStream();
            InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
            BufferedReader bufferedreader = new BufferedReader(inputstreamreader);

            String string = null;
            while ((string = bufferedreader.readLine()) != null) 
                System.out.println(string);
                System.out.flush();
            
         catch (Exception exception) 
            exception.printStackTrace();
        
    

而客户端代码是这样的:

<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->

    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <meta charset="utf-8">

    <script type="text/javascript">
        function onClick()
            var wrc_socket = new WebSocket('wss://localhost:9999');
            wrc_socket.onmessage = function(event) 
                alert('message = '+event.data);
            ;
            wrc_socket.onclose = function(event) 
                alert('Socket is close!');
            ;
            wrc_socket.onopen = function(event) 
                alert('Socket is open!');
            ;
            wrc_socket.send('Hi there!');
            alert('Done!');
        
    </script>
</head>

<body>
    <a href="#" onclick="onClick()">Test!</a>
</body>
</html>

我已经创建了私钥和公钥对,并将其导入到密钥库文件中,正如 here 所述。

我使用参数运行服务器应用程序:

-Djavax.net.ssl.keyStore=mySrvKeystore -Djavax.net.ssl.keyStorePassword=123456 -Djavax.net.debug=all

当我单击测试按钮时,我在 ssl 调试中收到此错误:

main, WRITE: TLSv1.2 Change Cipher Spec, length = 1
[Raw write]: length = 6
0000: 14 03 03 00 01 01                                  ......
Disconnected from the target VM, address: '127.0.0.1:64118', transport: 'socket'

由于某种原因,握手期间连接正在关闭。我无法弄清楚原因,请提出解决方案或一些想法来检查。

【问题讨论】:

您需要将服务器的证书(公钥)导入运行 JavaScript 的浏览器。将证书导入证书颁发机构证书存储区(因为它用于自签名)。 密钥包含在 apache 网络服务器的 https 配置中:像这样 SSLCertificateFile "/usr/local/apache/conf/cert/server.crt" SSLCertificateKeyFile "/usr/local/apache/conf /cert/server.key" 我认为 wss 连接在 https 之上进行,因此应该使用这些密钥。 你的术语到处都是。你没有自签名密钥,你有自签名证书。 服务器是否发送了CertificateRequest?如果是,客户端是否发送了证书? EJP,对于术语中的混乱感到抱歉。这方面有点新意。我在 ssl 调试中看不到证书请求:*** ServerHello, TLSv1.2 *** Certificate chain *** ECDH ServerKeyExchange *** ServerHelloDone 就是这样。之后客户端发送 *** ECDHClientKeyExchange *** Finished 【参考方案1】:

终于知道是什么原因了。在生成证书或密钥的过程中(无论什么...),我输入了假定的服务器名称,但在 wss 连接期间,地址是 ip - 因此,不匹配并且握手失败。

结论:确保您的 wss 使用与带有 ssl 的名称相同的 url。

【讨论】:

以上是关于如何使用自签名证书从 Javascript 连接到 SSL 服务器?的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 Alamofire 4.5 在本地连接到自签名证书保护的 Nginx

我可以在 JavaFX 中将自签名证书添加到我的 WebEngine 以连接到 https Web 服务器吗?

Jenkins 无法使用带有自签名证书的 HTTPS (HTTP + SSL) 连接到 SonarQube 服务器

将 nesjs 应用程序连接到 SQL Server Express 时出错:无法连接到 localhost:1433 - 自签名证书

如何信任 Android 上的自签名证书?

Xamarin Android 问题通过 HTTPS 连接到具有自签名证书的站点:“未找到证书路径的信任锚。”