当前位置:   article > 正文

创建 SSL证书并应用于WebSocket_websocket ssl

websocket ssl

写在前面

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

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

1.首先下载并安装 Win64 OpenSSL

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

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

内容如下:

  1. [ req ]
  2. default_bits = 2048
  3. default_keyfile = server-key.pem
  4. distinguished_name = subject
  5. req_extensions = req_ext
  6. x509_extensions = x509_ext
  7. string_mask = utf8only
  8. # The Subject DN can be formed using X501 or RFC 4514 (see RFC 4519 for a description).
  9. # Its sort of a mashup. For example, RFC 4514 does not provide emailAddress.
  10. [ subject ]
  11. countryName = Country Name (2 letter code)
  12. countryName_default = US
  13. stateOrProvinceName = State or Province Name (full name)
  14. stateOrProvinceName_default = NY
  15. localityName = Locality Name (eg, city)
  16. localityName_default = New York
  17. organizationName = Organization Name (eg, company)
  18. organizationName_default = Example, LLC
  19. # Use a friendly name here because its presented to the user. The server's DNS
  20. # names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
  21. # by both IETF and CA/Browser Forums. If you place a DNS name here, then you
  22. # must include the DNS name in the SAN too (otherwise, Chrome and others that
  23. # strictly follow the CA/Browser Baseline Requirements will fail).
  24. commonName = Common Name (e.g. server FQDN or YOUR name)
  25. commonName_default = Example Company
  26. emailAddress = Email Address
  27. emailAddress_default = test@test.com
  28. # Section x509_ext is used when generating a self-signed certificate. I.e., openssl req -x509 ...
  29. [ x509_ext ]
  30. subjectKeyIdentifier = hash
  31. authorityKeyIdentifier = keyid,issuer
  32. # You only need digitalSignature below. *If* you don't allow
  33. # RSA Key transport (i.e., you use ephemeral cipher suites), then
  34. # omit keyEncipherment because that's key transport.
  35. basicConstraints = CA:FALSE
  36. keyUsage = digitalSignature, keyEncipherment
  37. subjectAltName = @alternate_names
  38. nsComment = "OpenSSL Generated Certificate"
  39. # RFC 5280, Section 4.2.1.12 makes EKU optional
  40. # CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
  41. # In either case, you probably only need serverAuth.
  42. # extendedKeyUsage = serverAuth, clientAuth
  43. # Section req_ext is used when generating a certificate signing request. I.e., openssl req ...
  44. [ req_ext ]
  45. subjectKeyIdentifier = hash
  46. basicConstraints = CA:FALSE
  47. keyUsage = digitalSignature, keyEncipherment
  48. subjectAltName = @alternate_names
  49. nsComment = "OpenSSL Generated Certificate"
  50. # RFC 5280, Section 4.2.1.12 makes EKU optional
  51. # CA/Browser Baseline Requirements, Appendix (B)(3)(G) makes me confused
  52. # In either case, you probably only need serverAuth.
  53. # extendedKeyUsage = serverAuth, clientAuth
  54. [ alternate_names ]
  55. DNS.1 = test.com
  56. DNS.2 = www.test.com
  57. DNS.3 = mail.test.com
  58. DNS.4 = ftp.test.com
  59. # Add these if you need them. But usually you don't want them or
  60. # need them in production. You may need them for development.
  61. # DNS.5 = localhost
  62. # DNS.6 = localhost.localdomain
  63. # DNS.7 = 127.0.0.1
  64. # IPv6 localhost
  65. # 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/');

代码实现

控制台代码 

  1. using Fleck;
  2. using System.Security.Authentication;
  3. using System.Security.Cryptography.X509Certificates;
  4. public class WebSocketServerDemo
  5. {
  6. public static void Main(string[] args)
  7. {
  8. X509Certificate2 certificate = new X509Certificate2("C:\\test.com.pfx", "test");
  9. var server = new WebSocketServer("wss://0.0.0.0:7181");
  10. if (certificate != null)
  11. {
  12. server.Certificate = certificate;
  13. server.EnabledSslProtocols = SslProtocols.Ssl3 | SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
  14. //server.EnabledSslProtocols = SslProtocols.Tls12;
  15. }
  16. server.Start(socket =>
  17. {
  18. socket.OnOpen = () => Console.WriteLine("Open!");
  19. socket.OnClose = () => Console.WriteLine("Close!");
  20. socket.OnMessage = message =>
  21. {
  22. Console.WriteLine(message);
  23. socket.Send(message + " from server");
  24. };
  25. });
  26. Console.WriteLine("Server Started");
  27. Console.ReadLine();
  28. }
  29. }

客户端代码

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>WebSocket Demo</title>
  6. <script type="text/javascript">
  7. var start = function () {
  8. var inc = document.getElementById('incomming');
  9. var wsImpl = window.WebSocket || window.MozWebSocket;
  10. var form = document.getElementById('sendForm');
  11. var input = document.getElementById('sendText');
  12. inc.innerHTML += "connecting to server ...<br/>";
  13. // 创建新的websocket新连接端口为7181
  14. window.ws = new wsImpl('wss://test.com:7181/');
  15. // 当数据从服务器服务中心发送后,继续向下运行过程
  16. ws.onmessage = function (evt) {
  17. inc.innerHTML += evt.data + '<br/>';
  18. };
  19. // 当链接对象找到服务端成功对接后,提示正常打开
  20. ws.onopen = function () {
  21. inc.innerHTML += 'connection opened<br/>';
  22. };
  23. // 当链接对象未找找到服务端成功对接后,提示打开失败,别切单项关闭
  24. ws.onclose = function () {
  25. inc.innerHTML += 'connection closed<br/>';
  26. }
  27. form.addEventListener('submit', function (e) {
  28. e.preventDefault();
  29. var val = input.value;
  30. ws.send(val);
  31. input.value = "";
  32. });
  33. }
  34. window.onload = start;
  35. </script>
  36. </head>
  37. <body>
  38. <form id="sendForm">
  39. <input id="sendText" placeholder="Text to send" />
  40. </form>
  41. <pre id="incomming"></pre>
  42. </body>
  43. </html>

调用示例

IIS 站点配置

 

 

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号