示例代码:C# MQTTS双向认证(客户端)(服务器EMQX)

初级代码游戏的专栏介绍与文章目录-CSDN博客

我的github:codetoys,所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。

这些代码大部分以Linux为目标但部分代码是纯C++的,可以在任何平台上使用。

源码指引:github源码指引_初级代码游戏的博客-CSDN博客


目录

CA证书、客户端证书和私钥

emqx的MQTTS设置

客户端代码


CA证书、客户端证书和私钥

使用单向认证时客户端只需要确认服务器证书有效(也可以不确认),一般服务器自签名证书需要将服务器证书的签发者CA的证书放在客户机的受信任的证书签发机构里或程序直接读取CA证书文件。

证书包含公钥和CA的签名,别人通过验证证书正确性来确认你的身份,与证书对应的私钥则用来解密别人发给你的加密数据(用证书里的公钥加密,只有对应的私钥才能解密,这保证了只有你可以解密)。

CA证书原则上可以通过操作系统预置加上互联网检索来验证,但是很多时候用的是自签名的CA证书,上互联网验证是没用的,需要手动安装证书告诉操作系统这个证书我认可或者程序直接读取证书文件。

双向认证时服务端也要确认客户端的证书,因此客户端需要提供客户端证书和签发者的证书,并且客户端证书的签发机构也必须在服务器的受信任名单里。

一般情况下我们用服务器给的客户端证书,编程的时候需要的就是服务端给的CA证书(同时也是服务器证书的签发者)和客户端证书。

windows上包含私钥的证书多用pfx格式,unix/linux上则多用pem格式。格式的问题很头疼,我只能说我下面演示的代码在windows上正确执行了,不代表在linux上也能正确执行。

很多库使用三个文件:CA证书、证书、私钥,CA证书文件其实可以包含多个根证书,后两个是服务器或客户端的证书和私钥,多为pem格式。如果使用pfx格式就只需要两个文件:CA证书和pfx文件(同时包含证书和私钥)。

单独的证书和私钥多用.cer、.key的扩展名,其实格式一般也是pem文件,扩展名不同而已。pem文件格式可以包含多个私钥、证书(简单地堆进去即可)。

从两个pem生成一个pfx:

复制代码
openssl pkcs12 -export -out client.pfx -inkey client.key -in client.cer

其中key和cer都是pem格式(有时候也用pem后缀名)。

emqx的MQTTS设置

在浏览器里设置:

点击一下监听器的名称,右侧会显示详情,往下拉,重点在下面:

"验证服务器证书"开关打开才能选择证书文件,这几个证书是emqx安装的时候自带的。感觉这个"服务器"其实是客户端的意思,MQTT概念里并没有服务器、客户端,只有代理(broker)、发布者、订阅者。

verify_none不验证客户端证书,verify_peer验证客户端证书。

"Fail If No Peer Cert"这个选项有点坑,如果前面不是verify_peer,而客户端没有客户端证书,这个选项为true就一定会导致连接失败。按照常理既然选择可不验证客户端,那么这个选项应该被忽略才对。

上图的设置效果是必须使用双向验证。

客户端代码

cs 复制代码
//参数对象
MqttClientOptionsBuilder mqttClientOptions = new();

//常规的IP端口等参数
				_ = mqttClientOptions
				.WithTcpServer(hostname, port)
				//.WithProtocolVersion(MQTTnet.Formatter.MqttProtocolVersion.V311)
				.WithClientId(client_id)
				.WithCleanSession(false)
				.WithKeepAlivePeriod(TimeSpan.FromSeconds(30))
				.WithCredentials(userid, passwd);


//构造认证所需的参数

					X509Certificate2 caCert = new(caCertpath);//受信任的CA证书文件
					X509Certificate2 clientCert = new(clientCertpath);//客户端证书和私钥,如果是密码保护的pfx文件,可以用(.pfx,passwd)
					var newCert = new X509Certificate2(clientCert.Export(X509ContentType.SerializedCert));//怀疑这步就是为了去掉密码保护

					X509Certificate2Collection certificates = [];
					_ = certificates.Add(caCert);
					_ = certificates.Add(newCert);

					MqttClientTlsOptions tlsOptions = new MqttClientTlsOptions
					{
						UseTls = true,
						AllowUntrustedCertificates = false,
						SslProtocol = SslProtocols.None, //根据需要选择 TLS 版本,None表示系统选择,Default已经废弃 
						ClientCertificatesProvider = new DefaultMqttCertificatesProvider(certificates),//加载证书
						CertificateValidationHandler = ValidateCertifiCertificates//避免证书验证,关键!没这个连接不返回也不报异常
					};
					_ = mqttClientOptions.WithTlsOptions(tlsOptions); // tls选项
				

//连接,用的是MQTTnet.Client
public IMqttClient mqttClient;
mqttClient.ConnectAsync(mqttClientOptions.Build());

(这里是文档结束)

相关推荐
一只小小汤圆32 分钟前
c# 显示正在运行的线程数
开发语言·c#
vvilkim1 小时前
深入理解C# MVVM模式:从理论到实践
开发语言·c#
张鱼小丸子_微辣6 小时前
.Net Framework 4/C# 初识 C#
c#
明月看潮生8 小时前
青少年编程与数学 02-020 C#程序设计基础 15课题、异常处理
开发语言·青少年编程·c#·编程与数学
DanmF--8 小时前
C#面向对象实践项目--贪吃蛇
开发语言·游戏·c#·游戏程序
凌康ACG11 小时前
易语言使用OCR
c++·yolo·c#·ocr·易语言
InCerry11 小时前
.NET 9中的异常处理性能提升分析:为什么过去慢,未来快
c#·.net·高性能
@蓝莓果粒茶13 小时前
LeetCode第244题_最短单词距离II
c++·笔记·学习·算法·leetcode·职场和发展·c#
端阳月七14 小时前
C#面试问题61-80
开发语言·c#
蓝点lilac14 小时前
C# Task 取消执行的简单封装
c#·.net·多线程