创建 SSL证书并应用于WebSocket

写在前面

由于上一篇介绍 如何使用Fleck创建WebSocket服务器 ,感觉不够完善,因为生产环境中肯定是需要用到ssl的,而创建或申请ssl证书,相对而言是比较繁琐的事情,特别是本地如果要构建一个使用ssl的测试环境时,就难免要多费一番周折了。

本文介绍了如何创建一个 ssl 证书,用于test.com在本地环境中测试带安全验证的 WebSocket。

1.首先下载并安装 Win64 OpenSSL

建议把安装目录指定为 C:\OpenSSL-Win64\ 

2.然后创建openssl.cnf 并保存到如下目录:C:\OpenSSL-Win64\

内容如下:

[ req ]
default_bits        = 2048
default_keyfile     = server-key.pem
distinguished_name  = subject
req_extensions      = req_ext
x509_extensions     = x509_ext
string_mask         = utf8only

# The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
#   Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
[ subject ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = NY

localityName            = Locality Name (eg, city)
localityName_default        = New York

organizationName         = Organization Name (eg, company)
organizationName_default    = Example, LLC

# Use a friendly name here because its presented to the user. The server's DNS
#   names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
#   by both IETF and CA/Browser Forums. If you place a DNS name here, then you 
#   must include the DNS name in the SAN too (otherwise, Chrome and others that
#   strictly follow the CA/Browser Baseline Requirements will fail).
commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = Example Company

emailAddress            = Email Address
emailAddress_default        = test@test.com

# Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
[ x509_ext ]

subjectKeyIdentifier        = hash
authorityKeyIdentifier  = keyid,issuer

# You only need digitalSignature below. *If* you don't allow
#   RSA Key transport (i.e., you use ephemeral cipher suites), then
#   omit keyEncipherment because that's key transport.
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage  = serverAuth, clientAuth

# Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
[ req_ext ]

subjectKeyIdentifier        = hash

basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

# RFC 5280, Section 4.2.1.12 makes EKU optional
#   CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
#   In either case, you probably only need serverAuth.
# extendedKeyUsage  = serverAuth, clientAuth

[ alternate_names ]

DNS.1       = test.com
DNS.2       = www.test.com
DNS.3       = mail.test.com
DNS.4       = ftp.test.com

# Add these if you need them. But usually you don't want them or
#   need them in production. You may need them for development.
# DNS.5       = localhost
# DNS.6       = localhost.localdomain
# DNS.7       = 127.0.0.1

# IPv6 localhost
# DNS.8     = ::1

详细步骤

打开命令提示符窗口:

1.执行 cd "c:\OpenSSL-Win64\bin"

2.执行 set OPENSSL_CONF=c:\OpenSSL-Win64\openssl.cnf

3.执行 openssl req -x509 -newkey rsa:4096 -sha256 -nodes -keyout test.key -out test.crt -subj "/CN=test.com" -days 3650

如下图所示:

将C:\OpenSSL-Win64\bin目录下 test.crt 导入证书存储:

  1. 打开certlm.msc
  2. 转至受信任的根证书颁发机构 > 证书
  3. 右键单击某处,选择“所有任务”>“导入”
  4. 浏览刚刚创建的文件test.crt(位于 C:\OpenSSL-Win32\bin 中)
  5. 选择将所有证书放入以下存储中:受信任的根证书颁发机构
  6. 单击“完成”

从证书列表中导出此证书:

  1. 刷新受信任的根证书颁发机构 > 证书,找到并右键单击 test.com 证书
  2. 选择所有任务 > 导出
  3. 导出为test.p7b并保存在C:\OpenSSL-Win64\bin\
  4. 删除test.com证书存储中当前的证书

接着执行:openssl pkcs7 -in test.p7b -inform DER -out result.pem -print_certs

在执行:openssl pkcs12 -export -inkey test.key -in result.pem -name test.com -out final_result.pfx

过程中需要输入密码,后面要用到不要忘掉,建议保存一下。

将“final_result.pfx”导入证书存储区:

  1. 双击生成的final_result.pfx文件运行安装程序
  2. 选择本地机器
  3. 输入密码
  4. 选择将此密钥标记为可导出
  5. 选择包括所有扩展属性
  6. 选择将所有证书放入以下存储中:受信任的根证书颁发机构
  7. 单击“完成”

再次重复上述导入步骤 1 到 7,但这次在步骤 6 中,将证书放置在“Web宿主”证书存储中(以便 IIS 在绑定到 https 时可以看到该证书) 

从存储中导出此证书(以在套接字服务器应用程序中使用):

  1. 刷新受信任的根证书颁发机构 > 证书,找到并右键单击该test.com证书
  2. 选择所有任务 > 导出
  3. 选择yes,导出私钥
  4. 选择个人信息交换
  5. 如果可能,选择包括所有证书
  6. 选择导出所有扩展属性
  7. 选择启用证书隐私
  8. 添加密码
  9. 添加文件名test.com.pfx将其保存到 C:\ 或“套接字服务器应用程序”将引用它的位置,请参见下文
    X509Certificate2 certificate = new X509Certificate2("C:\\test.com.pfx", "password");

 将test.com与本地电脑 IP 一起添加到主机文件中,C:\Windows\System32\drivers\etc\hosts

创建 IIS 网站并为 http 和 https 添加到 test.com 的绑定(并在 https 绑定中选择 test.com 证书)

 ​访问 https://test.com/your-socket-client.htm (在 Chrome/Edge 中,当提示 ssl 警告时单击高级 > 继续)

套接字客户端现在应该使用 wss 成功连接wss://test.com:xxxx

注意事项

如果是用 Chrome 进行测试,则可能需要使用 TLS 1.2。因为Chrome貌似加强了可以使用的安全协议。另外要在套接字服务器上使用 TLS 1.2,请设置:
server.EnabledSslProtocols = SslProtocols.Tls12;
或更多选项,比如:
server.EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Ssl3 | SslProtocols.Tls11 | SslProtocols.Tls;

在套接字服务器上,尝试监听 0.0.0.0
var server = new WebSocketServer("wss://0.0.0.0:7181");

在客户端,如果使用wss,则需要使用ssl证书注册的域的url,而不是ip地址:
window.ws = new wsImpl('wss://test.com:7181/');

代码实现

控制台代码 

using Fleck;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
public class WebSocketServerDemo
{
    public static void Main(string[] args)
    {
        X509Certificate2 certificate = new X509Certificate2("C:\\test.com.pfx", "test");
        var server = new WebSocketServer("wss://0.0.0.0:7181");
        if (certificate != null)
        {
            server.Certificate = certificate;
            server.EnabledSslProtocols = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
            //server.EnabledSslProtocols = SslProtocols.Tls12;
        }
        server.Start(socket =>
        {
            socket.OnOpen = () => Console.WriteLine("Open!");
            socket.OnClose = () => Console.WriteLine("Close!");
            socket.OnMessage = message =>
            {
                Console.WriteLine(message);
                socket.Send(message + " from server");
            };
        });
        Console.WriteLine("Server Started");

        Console.ReadLine();
    }
}

客户端代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>WebSocket Demo</title>
    <script type="text/javascript">
        var start = function () {
            var inc = document.getElementById('incomming');
            var wsImpl = window.WebSocket || window.MozWebSocket;
            var form = document.getElementById('sendForm');
            var input = document.getElementById('sendText');

            inc.innerHTML += "connecting to server ...<br/>";

            // 创建新的websocket新连接端口为7181
            window.ws = new wsImpl('wss://test.com:7181/');

            // 当数据从服务器服务中心发送后,继续向下运行过程
            ws.onmessage = function (evt) {
                inc.innerHTML += evt.data + '<br/>';
            };

            // 当链接对象找到服务端成功对接后,提示正常打开
            ws.onopen = function () {
                inc.innerHTML += 'connection opened<br/>';
            };

            // 当链接对象未找找到服务端成功对接后,提示打开失败,别切单项关闭
            ws.onclose = function () {
                inc.innerHTML += 'connection closed<br/>';
            }

            form.addEventListener('submit', function (e) {
                e.preventDefault();
                var val = input.value;
                ws.send(val);
                input.value = "";
            });
        }
        window.onload = start;
    </script>
</head>
<body>
    <form id="sendForm">
        <input id="sendText" placeholder="Text to send" />
    </form>
    <pre id="incomming"></pre>
</body>
</html>

调用示例

IIS 站点配置

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/312750.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

记录一次数据中包含转义字符\引发的bug

后端返回给前端的数据是: { "bizObj": { "current": 1, "orders": [ ], "pages": 2, "records": [ { "from": "1d85b8a4bd33aaf99adc2e71ef02960e", …

【办公技巧】Word功能区灰色显示不能编辑,怎么破?

Word文档可以设置加密来保护文件禁止修改&#xff0c;但是在word文档中设置限制编辑功能时对它的作用是否有详细的了解呢&#xff1f;今天为大家介绍word限制编辑功能的作用以及忘记了限制编辑密码该如何解决。 设置限制大家应该都清楚&#xff0c;就是点击工具栏中的审阅 – …

如何让GPT/GPT4成为你的编程助手?

详情点击链接&#xff1a;如何让GPT/GPT4成为你的编程助手&#xff1f; 一OpenAI 1.最新大模型GPT-4 Turbo 2.最新发布的高级数据分析&#xff0c;AI画图&#xff0c;图像识别&#xff0c;文档API 3.GPT Store 4.从0到1创建自己的GPT应用 5. 模型Gemini以及大模型Claude2二…

Edge扩展插件安装

目录 一、 Edge扩展插件安装步骤 1.1 打开 Edge 浏览器&#xff0c;并点击右上角的菜单按钮&#xff08;三个水平点&#xff09;。 1.2 在菜单中选择“扩展”选项。 1.3 在扩展页面通过“查找新扩展”来找到你想要安装的扩展插件。 ​编辑 1.4 搜索插件 1.5 在详情页面中…

数据交付变革:研发到产运自助化的转型之路

作者 | Chris 导读 本文讲述为了提升产运侧数据观察、分析、决策的效率&#xff0c;支持业务的快速迭代&#xff0c;移动生态数据研发部对数仓建模与BI工具完成升级&#xff0c;采用宽表建模与TDA平台相结合的方案&#xff0c;一站式自助解决数据应用需求。在此过程中&#xff…

SpringBoot 集成 Kafka 高级实现

1、简介 之前博客中记录了直接使用Kafka客户端实现生产者和消费者之间的交互&#xff0c;这种方式通过设置各种参数编码繁琐&#xff0c;因此通过SpringBoot集成Kafka成为一种常用的实现&#xff0c;下面就详细介绍 SpringBoot 是如何和Kafka进行集成的&#xff0c;本文主要参考…

响应式Web开发项目教程(HTML5+CSS3+Bootstrap)第2版 例3-4 CSS 立方体

代码 <!doctype html> <html> <head> <meta charset"utf-8"> <title>CSS 立方体</title> <link href"CSS/style.css" rel"stylesheet" type"text/css"> <style> .box {width: 200px…

解密!神奇代码消除 Vue 中 Mac 电脑左滑右滑页面跳转

想知道如何让Mac电脑左滑右滑不再意外跳转页面吗&#xff1f;本文将揭示一个独家秘籍&#xff0c;通过简单的一行代码&#xff0c;让你的用户体验飞速提升&#xff01;别错过这个让你的Vue表格组件更顺畅的宝贵技巧&#xff01; 最近&#xff0c;我在使用 Vue 开发表格组件时遇…

初识Hadoop-概述与关键技术

一.大数据概述 1.什么是大数据 高速发展的信息时代&#xff0c;新一轮科技革命和变革正在加速推进&#xff0c;技术创新日益成为重塑经济发展模式和促进经济增长的重要驱动力量&#xff0c;而“大数据”无疑是核心推动力。 那么&#xff0c;什么是“大数据”呢&#xff1…

odoo linux环境打印乱码或无内容

在odoo打印中会遇到乱码或者无内容显示&#xff0c;需要安装一些包 sudo apt-get install ttf-wqy-zenhei sudo apt-get install ttf-wqy-microhei安装前 安装后

Oladance、南卡、Cleer开放式耳机怎么样?全方位测评大PK!

​开放式耳机作为新兴的音频设备领域中备受欢迎的选择&#xff0c;但市场上琳琅满目的产品汇集了质量千差万别的耳机&#xff0c;其中存在着一些粗制滥造的产品。身为一位音频设备测评博主&#xff0c;我经常收到有关哪个品牌的开放式耳机质量好的疑问。面对市面上众多选择&…

数据结构(三)堆和哈希表

目录 哈希表和堆什么是哈希表 &#xff1f;什么是堆 &#xff1f;什么是图 &#xff1f;案例一&#xff1a;使用python实现最小堆案例二 &#xff1a; 如何用Python通过哈希表的方式完成商品库存管理闯关题 &#xff08;包含案例三&#xff1a;python实现哈希表&#xff09; 本…

谷歌浏览器安装不在默认安装位置Selenium无法打开解决方法

Selenium之cannot find Chrome binary错误-CSDN博客 上面是我找的解决方案的链接 通过option.setBinary()的方法来指定谷歌浏览器的实际运行文件路径&#xff1b; 下面是结合我这边具体情况下写的代码 option.setBinary()中的路径是谷歌浏览器运行文件的路径&#xff1b;Sy…

SGX Enclave Measurement

文章目录 前言一、简介二、Measuring ECREATE三、Measuring Enclave Attributes四、Measuring EADD五、Measuring EEXTEND六、Measuring EINIT 前言 本文来自 Intel SGX Explained 一、简介 SGX&#xff08;Intel Software Guard Extensions&#xff09;实现了一种软件认证方…

Java多线程并发篇----第八篇

系列文章目录 文章目录 系列文章目录前言一、简述一下你对线程池的理解二、线程生命周期(状态)三、新建状态(NEW)四、就绪状态(RUNNABLE)五、运行状态(RUNNING)前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站…

基于Python的在线考试系统-计算机毕业设计源码78268

摘 要 本论文主要论述了如何使用python语言、Django框架开发一个在线考试系统&#xff0c;本系统将严格按照软件开发流程&#xff0c;进行各个阶段的工作&#xff0c;面向对象编程思想进行项目开发。在引言中&#xff0c;作者将论述该系统的当前背景以及系统开发的目的&#xf…

Memory Wall in Neural Network Inference

Memory Wall in Neural Network Inference 神经网络推理的瓶颈在于访存带宽&#xff0c;通常无法发挥出加速器的全部算力。本文总结了目前常用的推理加速器及其设计&#xff0c;并分析了常用神经网络的访存瓶颈。文章大部分内容参考自Computer Architecture: A Quantitative A…

审稿变慢?还疯狂拒稿?这本毕业神刊如今争议不断,还值得一投吗?

【SciencePub学术】 IEEE ACCESS 期刊评说 网友辣评 评说1&#xff1a;麻了&#xff0c;11月17收到外审&#xff0c;现在意见还没回来啊&#xff0c;神刊肿么了&#xff1f; 评说2&#xff1a;两个审稿人评审的&#xff0c;一个拒绝&#xff08;最终意见大修&#xff09;&…

SpringBoot 把PageHelper分页信息返回给前端

第1步&#xff1a;定义线程容器收纳HttpHeaders和HttpStatus import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus;public class ResponseUtils {private static ThreadLocal<HttpHeaders> ThreadLocalHeaders new InheritableT…

07- OpenCV:模糊图像

目录 一、模糊原理 二、模糊的相关处理方法&#xff1a; 1、均值滤波&#xff08;归一化盒子滤波&#xff09; 2、高斯滤波&#xff08;正态分布的形状&#xff09; 3、中值模糊 4、双边模糊算法&#xff08;美容软件&#xff09; 5、相关代码&#xff1a; 6、几种模糊算法的比…