当前位置: 首页 > news >正文

示例代码: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就一定会导致连接失败。按照常理既然选择可不验证客户端,那么这个选项应该被忽略才对。

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

客户端代码

//参数对象
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());

(这里是文档结束)

相关文章:

  • 【Elasticsearch】多字段查询方式汇总
  • 【VS2022】创建本地仓库,开启Git管理控制
  • 笔记8——模式匹配 match语句(仅在Python 3.10及以上版本中可用)
  • Qt工作总结03 <qSort按某一属性进行排序>
  • SpringAI集成DeepSeek实战
  • 【Linux网络-网络基础】计算机网络背景+协议+OSI七层模型
  • 解释 Git 的基本概念和使用方式。
  • 渗透利器:Burp Suite 联动 XRAY 图形化工具.(主动扫描+被动扫描)
  • 2025前端面试题超全面解析(附答案与深度扩展)
  • PicoShare实操:轻松实现远程文件共享无需公网IP与云服务器
  • 大数据学习之SparkStreaming、PB级百战出行网约车项目一
  • 华纳云:如何从服务器日志中发现僵尸进程?
  • UGUI Canvas为Overlay模式下的UI元素的position和localPosition
  • 2月14日笔记
  • 安装OpenJDK21(linux、macos)
  • 站群服务器和普通服务器有哪些不同之处?
  • 【分布式理论9】分布式协同:分布式系统进程互斥与互斥算法
  • 软著申请(一)实名认证【2025年最新版】
  • 在本地校验密码或弱口令 (windows)
  • 汽车 OTA 升级:提升下载与升级速度,优化用户体验
  • 2025世界数字教育大会将于5月14日至16日在武汉举办
  • 虚假认定实质性重组、高估不良债权价值,原中国华融资产重庆分公司被罚180万元
  • “上海之帆”巡展在日本大阪开幕,松江区组织企业集体出展
  • 复旦设立新文科发展基金,校友曹国伟、王长田联合捐赠1亿助力人文学科与社会科学创新
  • 黄仁勋:中国AI市场将达500亿美元,美国企业若无法参与是巨大损失
  • 福特汽车撤回业绩指引,警告关税或造成15亿美元利润损失