温故知新,signalR、RSA加密、ConcurrentQueue队列
博客园 2023-06-27 14:32:26
这是一个用户密码异步加解密的Demo,包含了RSA非对称加密,ConcurrentQueue线程安全队列使用,signalR实时推送加解密信息等内容。
说在前面的话

距离上次更新已然快过去一年了,这中间日子里进入了非常繁忙的项目迭代开发中,时至今日终于有空停下来写一写之前的博客计划,续更后的第一篇,温故知新,用一个Demo介绍技术点的落地实操,如有不同意见评论区留下你的想法,Of course ,如果你杠精就是你对。


(相关资料图)

依照惯例,源代码在文末,需要自取~

不同解决方案?

直接看看执行效果,看完之后,你是否会与我选择同样的技术方案呢?

实现效果

一个用户列表,可以展示所有用户的信息,需要对其中的密码进行加密,加密使用非对称加密,点击加密按钮以及解密按钮,实时地可以看到加密和解密的数据。

乍一看看可太简单,RSA的非对称加密,网上直接ctrl C V一套已有的就完事,就是要解决实时性的问题。

这里我选择了SignlR做实时推送,然后为了可以看到效果与性能考虑,使用了ConcurrentQueue线程安全队列,控制加解密的速度。

好了砖头抛出来了,看各位大佬骚操作

拉代码看代码

如果你不晓得这几个技术点该如何加入你的框架中,或者知道一些概念,但是没用过,下文适合你食用!

RSA加解密

非对称加密的使用现在已然太多示例,提供的项目源代码中,专门提供了一个可以直接跑的Demo,拉下来F5,调试一下完事,贴心的为你提供了Web API接口与测试页面。

QueueDemo 作为WebApi启动, RSAProcessing.MVC 作为前端页面启动

一下就是核心 RSA加密处理程序的核心代码,Ctrl C V之后, 使用 RSAProcessing.GenerateKeys(out string publicKey, out string pricateKey);即可生成公钥和秘钥,加密解密使用方式同上。

///     /// RSA加密处理程序    ///     public static class RSAProcessing    {        ///         ///  生成RSA密钥对        ///         ///         ///         public static void GenerateKeys(out string publicKey, out string privateKey)        {            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())            {                publicKey = rsa.ToXmlString(false);                privateKey = rsa.ToXmlString(true);            }        }        ///         ///  使用公钥加密文本        ///         ///         ///         ///         public static string Encrypt(string plainText, string publicKey)        {            byte[] plainBytes = Encoding.UTF8.GetBytes(plainText);            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())            {                rsa.FromXmlString(publicKey);                byte[] encryptedBytes = rsa.Encrypt(plainBytes, false);                return Convert.ToBase64String(encryptedBytes);            }        }        ///         ///  使用私钥解密文本        ///         ///         ///         ///         public static string Decrypt(string encryptedText, string privateKey)        {            byte[] encryptedBytes = Convert.FromBase64String(encryptedText);            using (RSACryptoServiceProvider rsa = new RSACryptoServiceProvider())            {                rsa.FromXmlString(privateKey);                byte[] decryptedBytes = rsa.Decrypt(encryptedBytes, false);                return Encoding.UTF8.GetString(decryptedBytes);            }        }......
SignlR的实时推送

SignlR是什么?这个不用我去百度,ChatGPT可以给你一个简洁有效的答案。

看到这里,可能你会有和我一样感受,这个作为实时通讯,是不是我直接做一个仿QQ和微信的聊天工具来,做大做强? 看看 GPT的回答:

可以看到ChatGPT可以给予我们绝大部分答案,但是这里给大家补充一下:

通讯方式的选择取决于浏览器版本以及服务端和客户端能力范围内的最佳通讯方式,通常是WebSocket > Server-Sent Events > Long PolingSignalR不仅仅可在线聊天的通讯软件,做事件推送也非常好用,例如直播或者视频的观看人数统计等等SignlR的.net 6代码实现

使用之前,一定先去看看微软的官方Demo!https://learn.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-6.0

以上是简易的两个Web应用的架构图,5102的WebApi作为服务端提供数据,MVC 应用作为客户端接受数据,以及发送SignalR连接,因为他们是两个Web应用,所属的web域不同,客户端请求服务端,需要服务端配置允许跨域请求。

注册服务

在5102的服务端中注册SignalR ,并且配置允许跨域

builder.Services.AddCors(options =>{    options.AddDefaultPolicy(builder =>    {        builder.AllowAnyMethod()               .AllowAnyHeader()               .WithOrigins("http://localhost:5067")               .AllowCredentials(); // 允许包含凭据;    });});builder.Services.AddSignalR();...注册其他的服务...  var app = builder.Build();app.UseCors();app.MapHub("/queueHub");  // 配置路由
配置消息处理中心

在持久性连接的基础上,SignalR提供了一个更高层次的抽象层:Hub,基于javascript的灵活性和C#的动态特性,Hub是一个至关重要的开发模式,它消弭了客户端和服务端这两个独立的物理环境之间的界限。 在Web环境中最通用的使用模式允许我们透明地在客户端和服务端之间进行方法调用。

简单的说,就是双向RPC,即可以直接从客户端调用服务器端的方法,同时服务端也可以调用客户端的方法。

using Microsoft.AspNetCore.SignalR;namespace QueueDemo.Core{    ///     /// 队列的signalR总线    ///     public class QueueHub : Hub    {        ///         /// 加入连接的事件        ///         ///         public override async Task OnConnectedAsync()        {            GlobalUserInfo.Clients = Clients;            await base.OnConnectedAsync();        }        ///         /// signalR推送加密信息        ///         /// 用户id        /// 加密数据        ///         public async Task SendEncryptDequeue(int userId, string message)        {            await GlobalUserInfo.Clients.All.SendAsync("ReceiveEncrypt", userId, message);        }        ///         ///  signalR推送解密信息        ///         /// 用户id        /// 解密数据        ///         public async Task SendDecryptDequeue(int userId, string message)        {            await GlobalUserInfo.Clients.All.SendAsync("ReceiveDecrypt", userId, message);        }    }}
客户端JS配置

客户端主要需要做的就是,与SignalR服务端建立连接,接受服务端推送过来的数据。

<script>    let queueHost = "http://localhost:5102";    // 创建signalR连接    var connection = new signalR.HubConnectionBuilder().withUrl(queueHost + "/queueHub").build();    // 接收到  ReceiveEncrypt 的消息    connection.on("ReceiveEncrypt", function (userId, message) {        console.log(userId);        console.log(message);        // 使用特定 id 来定位并修改文本内容        $("#en_" + userId).text(message);    });    //  接收到  ReceiveDecrypt 的消息    connection.on("ReceiveDecrypt", function (userId, message) {        console.log(userId);        console.log(message);        // 使用特定 id 来定位并修改文本内容        $("#de_" + userId).text(message);    });    // 连接成功    connection.start().then(function () {        console.log("Connection Success")    }).catch(function (err) {        return console.error(err.toString());    });</script>
ConcurrentQueue队列连接客户端与服务端

SignalR与QueueHub的连接已然搞定,就是如何触发推送加解密信息。

这里使用的方案是ConcurrentQueue队列,将所有的用户信息推送到加密队列(&解密队列)中,出队一个UserInfo,就加密(&解密)一个用户信息,随后利用SignalR推送一个加密解密信息。

再说到队列,大家熟知都是RabbitMQ ,Kafka , RocketMQ,然而在实战中,急着要用一个队列,如果此时用上RabbitMQ,那么还需要额外部署一个应用,开防火墙等等,这一套搞下来,加上走流程快的话一周过去了,此时用一个内存队列就是最合适的,用线程加内存队列可以做一个低配版的rabbitmq,先实现业务需求,再后期去升级。

初始化队列

依上述所言,队列为了简单易用,在StartUp中创建两个线程去跑。

// 创建并启动后台任务            UserQueueHandler ledgerQueue = new(new QueueHub());Task task = Task.Run(() => ledgerQueue.DeProcessQueue(builder.Services, GlobalUserQueue.DecryptCancelToken.Token));Task task2 = Task.Run(() => ledgerQueue.EnProcessQueue(builder.Services, GlobalUserQueue.EncryptCancelToken.Token));

两个全局的静态变量存储队列的配置,并且创建两个中断循环的开关。

///   /// 全局用户队列初始化  ///   public static class GlobalUserQueue  {      ///       /// 解密队列 退出循环开关      ///       public static CancellationTokenSource DecryptCancelToken = new();      ///       /// 加密队列 退出循环开关      ///       public static CancellationTokenSource EncryptCancelToken = new();      ///       /// 解密队列      ///       public static ConcurrentQueue DecryptQueue = new();      ///       /// 加密队列      ///       public static ConcurrentQueue EncryptQueue = new();  }
初始化用户队列处理程序
///     /// 用户队列处理程序    ///     public class UserQueueHandler    {        private QueueHub _queueHub;        ///         /// 注入队列总线        ///         ///         public UserQueueHandler(QueueHub queueHub)        {            _queueHub = queueHub;        }        ///         /// 启动解密队列        ///         /// 注册服务        /// 退出Token控制器        ///         public async Task DeProcessQueue(IServiceCollection services, CancellationToken cancellationToken)        {            try            {                var serviceProvider = services.BuildServiceProvider();                // Rsa加解密服务                var rsaService = serviceProvider.GetRequiredService();                await Console.Out.WriteLineAsync($"Decrypt ProcessQueue Start! ");                while (true)                {                    cancellationToken.ThrowIfCancellationRequested();                    if (cancellationToken.IsCancellationRequested)                    {                        break;                    }                    // 解密队列出队                    if (GlobalUserQueue.DecryptQueue.TryDequeue(out DecryptRequest deRequest))                    {                        await Console.Out.WriteLineAsync($"DeProcessQueue UserIndexId -- {deRequest.UserIndex} -- {JsonConvert.SerializeObject(deRequest)} ");                        try                        {                            // 解密                            var deScryptRsp = rsaService.Decrypt(deRequest);                            if (deScryptRsp != null)                            {                                var userInfo = GlobalUserInfo.UserInfos.First(x => x.Index == deScryptRsp.UserIndex);                                userInfo.DecryptedPwd = deScryptRsp.DecryptedPwd;                                // 推送解密信息到前端                                await _queueHub.SendDecryptDequeue(userInfo.UserId, userInfo.DecryptedPwd);                                await Console.Out.WriteLineAsync($"DeProcessQueue Success! UserId--{userInfo.UserId} UserIndex--{deScryptRsp.UserIndex} ");                            }                            await Task.Delay(1000);                        }                        catch (Exception ex)                        {                            await Console.Out.WriteLineAsync($"DeProcessQueue Error --{JsonConvert.SerializeObject(ex)} ");                        }                    }                    else                    {                        // 队列中无数量 则休眠10秒                        await Task.Delay(10000);                    }                }            }            catch (Exception ex)            {                await Console.Out.WriteLineAsync(ex.Message);                throw;            }        }}

这个方法就是触发推送加解密的信息,连接客户端和服务端的核心。

ConcurrentQueue出队使用的是 GlobalUserQueue.DecryptQueue.TryDequeue(out DecryptRequest deRequest)利用serviceProvider.GetRequiredService();获取RSA解密服务,然后再调用解密方法。拿到解密之后的信息之后,使用queueHub的方法await _queueHub.SendDecryptDequeue(userInfo.UserId, userInfo.DecryptedPwd);推送解密数据推送数据主要是SignalR的方法 await GlobalUserInfo.Clients.All.SendAsync("ReceiveDecrypt", userId, message);总结

稍微总结一下,

Demo集成了RSA加密、SignalR推送、内存版的队列。讲解了一下SignalR的用法以及注意事项内存版的队列在Web应用中的优势有更好的更快速的解决方案评论区留下信息项目拉取下来,在解决方案设置中,同时启动两个项目即可。源代码仓库https://github.com/OrzCoCo-Y/QueueDemo参考资料

【微软文档】 https://learn.microsoft.com/zh-cn/aspnet/core/signalr/introduction?view=aspnetcore-6.0【ChatGPT】

温故知新,signalR、RSA加密、ConcurrentQueue队列

2023-06-27 14:32:26

中国电信新疆公司举办“2023年度新疆电信高考志愿填报”公益讲座

2023-06-27 13:58:14

精神体是什么物质_精神体是什么

2023-06-27 12:57:24

丰田宣布与日本初创企业合作开发钙钛矿电池 力争2030年用于电动汽车 当前看点

2023-06-27 12:50:22

支付宝里每次少几十块钱怎么回事 天天即时

2023-06-27 12:12:53

成都大邑、彭州2宗地块以底价3.81亿元成交 视讯

2023-06-27 11:51:45

中建七局海淀大悦城项目开展趣味运动会 世界报资讯

2023-06-27 11:15:06

天天即时:字字诛心_字字珠玑是什么意思

2023-06-27 10:42:26

全球快资讯:多处公共场所贴出警示:穿洞洞鞋乘扶梯易受伤!

2023-06-27 10:30:33

杭州这场主题晚会,把“廉洁好家风”的故事讲给大家听|今日聚焦

2023-06-27 09:56:36

焦点滚动:热热热!北京今日高温卷土重来 最高气温将达39℃

2023-06-27 09:52:57

分红哪家强? 160只股股息率超5%

2023-06-27 09:02:45

吉林省多地开展禁毒宣传活动_天天头条

2023-06-27 08:57:14

联合国难民署:2024年将有超过240万难民需要重新安置

2023-06-27 08:24:45

电科院创始人去世!此前父子反目:儿子被免董事长,夺公章还将父亲告上法庭

2023-06-27 08:04:00

焦点短讯!健康小站 | 痒痒痒!湿哒哒的梅雨时节警惕这些疾病

2023-06-27 07:01:25

www sexlnsex net|观点

2023-06-27 06:07:06

动态焦点:【探秘市场监管重点实验室】5G通信、电磁兼容、低音炮,这个“车联网”重点实验室不一般

2023-06-27 05:15:09

无线键盘失灵鼠标能用_无线键盘没反应但鼠标能用

2023-06-27 04:40:50

播报:幸福生活作文400字左右_幸福生活

2023-06-27 01:58:22

环球快看:2023-06-27 00:07广西高速公路最新路况实时播报

2023-06-27 00:40:30

海南自由贸易港封关前禁毒三年“固本防风险”启动仪式在海口举行 全球百事通

2023-06-26 22:40:05

瓦格纳事件后,俄国防部长绍伊古现身特别军事行动区 环球简讯

2023-06-26 21:59:16

今头条!羊排汤的做法羊肉炖萝卜_羊排汤的做法

2023-06-26 21:08:49

央行年中加码千亿元逆回购,下半年还有哪些货币政策可期

2023-06-26 20:14:38

天天快看:水果果盘造型图片(水果摆盘简单造型图片)

2023-06-26 19:43:35

最新工资价位表来了!你是什么段位?_重点聚焦

2023-06-26 19:03:23

要闻速递:各地各部门通过多种形式不断提高人民群众识毒、防毒、拒毒意识

2023-06-26 18:58:12

沈黎辉 沈辉是哪里人

2023-06-26 18:02:20

世界观点:消息称谷歌正开发 YouTube Playables 云游戏服务

2023-06-26 18:02:53

巨星传奇:引领低碳生活 创造美好未来

2023-06-26 17:37:27

伟仕佳杰6月26日斥资约53.36万港元回购13.4万股 全球快看点

2023-06-26 16:56:12

世界快报:玻璃翠怎样修剪才好看_玻璃翠什么季节修剪 玻璃翠什么时候修剪

2023-06-26 17:00:06

文化退(300089)龙虎榜数据(06-26) 环球热议

2023-06-26 16:13:18

荒无人烟的西伯利亚,其实是名副其实的“聚宝盆” 环球速递

2023-06-26 16:08:43

6月26日振江股份跌5.75%,兴全合润混合(LOF)基金重仓该股-环球滚动

2023-06-26 15:33:29

天天即时看!机构:四线城市近半月房价总体呈现下降态势

2023-06-26 15:06:26

鑫惠一生年金保险怎么样?有必要买吗?

2023-06-26 14:51:11

菲林格尔:新发展集团所持16.49%公司股份被司法冻结-世界实时

2023-06-26 14:29:47

think highly of sb_think highly of|世界通讯

2023-06-26 13:43:33

杨丽萍作品《孔雀》羊城连演7场,将迎来2022版百场演出

2023-06-26 13:04:48

高质量发展调研行|飘香林果富山乡

2023-06-26 11:22:03

有研泰国产业基地电解铜生产线设备安装启动

2023-06-25 16:04:41

世界最新:平舆县双庙乡 人居环境齐整治 美丽乡村“持久美”

2023-06-25 15:39:33

2023山西省高龄补贴发放标准 2023山西省老人高龄补贴有多少(完整版)-天天信息

2023-06-25 15:19:23

北京中考首日 各考点做足准备积极应对高温|播资讯

2023-06-25 15:05:48

安逸花欠2万逾期了被起诉会坐牢吗?被起诉怎么解决?

2023-06-25 14:21:12

天天精选!御龙在天捡东西有快捷键吗_不要自动的

2023-06-25 13:55:24

当前动态:*ST美尚申请“摘帽”,公司拟遭1330万处罚

2023-06-25 13:07:17

微信怎么登录qq 2023微信登录QQ号教程[多图]-全球关注

2023-06-25 12:11:09

各地加大研发实现粮食利用最大化 耕好“无形良田”守好“大国粮仓”|今日要闻

2023-06-25 11:50:28

开通2个月 厦门港首条“大三通”跨境电商海运快线吞吐量超12000标箱|当前动态

2023-06-25 11:29:32

世界关注:非法获取公民个人信息罪的犯罪构成要件具体有什么

2023-06-25 11:02:27

海南高考成绩公布!本科批普通类分数线483分-世界通讯

2023-06-25 10:20:02

神域之巅 天天讯息

2023-06-25 09:58:25

世界观天下!都说千金难买老来瘦,真的是越瘦越好?

2023-06-25 09:33:57

存在即合理是谁说的

2023-06-25 09:09:55

自主可控 高端突围 “工业母机”步入加速成长期

2023-06-25 08:26:18

637分!“敬礼娃娃”收到北大、人大邀请|环球视讯

2023-06-25 07:36:03

世界看点:既用于简易计税项目又用于一般计税项目的进项税可以抵扣吗 什么是简易计税和一般计税

2023-06-25 06:09:53

微博编辑文章在哪里_新浪微博文章编辑器|天天通讯

2023-06-25 05:11:12

每日观点:篮球球衣号码字体下载_篮球球衣号码的含义

2023-06-25 02:06:29

世界无烟日的由来视频_世界无烟日的由来 天天看热讯

2023-06-24 22:59:35

普京称不会让俄罗斯分裂 俄多地进入反恐行动状态

2023-06-24 22:03:40

有哪些关于北京的纪录片_有哪些关于北京的冷知识

2023-06-24 20:42:07

火锅配菜一般什么菜好吃 新视野

2023-06-24 19:46:40

每日精选:视频|孙燕姿、周深、张杰、二手玫瑰……众星亮相青岛凤凰音乐节

2023-06-24 18:16:07

【评论】简评古龙七种武器系列

2023-06-24 17:30:13

今日视点:我科学家揭秘河蚌铰链为何耐疲劳

2023-06-24 16:33:39

银川开展为期一个月公共安全隐患排查整治专项行动-环球速递

2023-06-24 15:37:37

6月25日开始喜迎千万横财,鸿运当头,3生肖钞票滚滚来

2023-06-24 14:52:10

石家庄:全面提升供热运行保障水平 供热设施“冬病夏治”正当时

2023-06-24 13:26:57

热点在线丨快乐假期,注意这几点

2023-06-24 12:18:38

美国制裁成废纸一张,日本半导体“放水”,悄悄进入俄罗斯_微资讯

2023-06-24 11:39:21

看热讯:你是故人来笔趣阁(你是故人来)

2023-06-24 10:37:03

当前观点:番茄长在哪里(番茄长在哪里的)

2023-06-24 09:59:29

21种简单编发教程 图解5款当下最流行的编发教程

2023-06-24 09:07:36

前5月查获进境濒危动植物及其制品7800余件

2023-06-24 08:06:20

水暖空调厂家批发(水暖空调)

2023-06-24 07:12:03

国药控股河南股份有限公司_国药控股是什么性子单位_前沿资讯

2023-06-24 06:00:12

流动负债率多少合适_流动负债率多少比较好

2023-06-24 05:13:03

mx8调音台的使用方法_mx8调音台调试教程

2023-06-24 02:09:26

官方:2025世俱杯将在美国举办这是改制后举办的...

2023-06-24 00:34:20

流星粉耳兔

2023-06-23 21:55:44

发布高温红色预警27条 河南启动重大气象灾害(高温)Ⅳ级应急响应

2023-06-23 21:01:32

股票000018|焦点观察

2023-06-23 19:51:37

23届选秀大会盘点:状元无悬念,火箭20号签捡宝,湖人选小德隆!|焦点热闻

2023-06-23 18:52:48

在绍兴装修合同纠纷找什么律师解决 头条焦点

2023-06-23 17:58:16

张杰和谢娜是怎么认识的_张杰和谢娜是怎么认识的? 全球报道

2023-06-23 17:11:11

今日最新!泛海集团(00129.HK)6月23日收盘平盘,主力资金净流出12.2万港元

2023-06-23 16:37:21

最新:第七届全国残疾人职业技能大赛吉祥物“泉能能”揭晓

2023-06-23 15:35:49

世界短讯!百思买BBY.USQ2营收好于预期 净利润同比暴跌58.31%

2023-06-23 14:57:54

夏天喝热水头晕_夏天喝热水的好处

2023-06-23 13:51:55

史料分类有哪些方面_史料分类有哪些

2023-06-23 12:58:22

欠款无力偿还被起诉了怎么办?最坏的结果是什么?

2023-06-23 12:23:07

哥特体26个英文字母(哥特体)

2023-06-23 11:38:15

炎黄吧_关于炎黄吧介绍-环球观焦点

2023-06-23 10:46:51

【世界播资讯】吉吉国王是啥梗 吉吉国王的意思

2023-06-23 10:06:10

当前报道:黑铁锭用途 黑铁锭配方

2023-06-23 09:14:45

全球观察:刘诗诗端午节请剧组吃点心 王一栩晒淮竹拍立得感谢

2023-06-23 09:02:51