您现在的位置是:网站首页> 编程资料编程资料
基于SignalR的消息推送与二维码扫描登录实现代码_实用技巧_
2023-05-24
555人已围观
简介 基于SignalR的消息推送与二维码扫描登录实现代码_实用技巧_
1 概要说明
使用微信扫描登录相信大家都不会陌生吧,二维码与手机结合产生了不同应用场景,基于二维码的应用更是比较广泛。为了满足ios、android客户端与web短信平台的结合,特开发了基于SinglarR消息推送机制的扫描登录。本系统涉及到以下知识点:
SignalR:http://signalr.net/ 这官网,ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务器代码可以立即向其推送内容,而不是让服务器等待客户端请求新的数据。
二维码:使用的QRCode类库,https://github.com/jeromeetienne/jquery-qrcode
MVC5:开发环境是基于MVC5

2、系统关系图
在实现本功能前,有点不是太确定能否拿下。
所谓万事开头难,通过查询想资料及自己归纳分析:系统涉及到手机客户端、浏览者、服务端,实现扫描登录也就是三者之间是如何协调工作的。通过axure画出如下关系图:

移动客户端、浏览者、服务端三者协作关系图
【M】:表示移动端 【B】:表示浏览者(浏览器客户端) 【S】:服务端,消息推送者及扫描认证接口发布者
步骤说明:
Step(步骤)1 ,【B】浏览登录页面,Step2【S】产生一个标识符UUID,并推送给B,生成登录二维码;
Step3,【M】扫描二维码,前提条件是【M】已登录,Step4【M】解析二维码信息获取UUID;
Step5,【M】向服务端发送UUID+登录信息,Step6【S】对UUID+登录信息进行相关解析认证,Step6 UUID认证,不通过认证,则到Step6-1 重新生成UUID循环Step 2与并Step6-2 返回给【M】UUID认证失败原因,Step6 通过认证,Step6-2转到登录信息认证,Step 7登录信息认证,失败Step7-3重新生成UUID循环Step 2,成功则Step7-1推送给【B】跳转到首页。
3、SignalR循环消息推送
3.1 引用SignalR
由于本人用的是VS15Preview4,可以直接使用Nuget可视化管理工具进行安装:Tools—>Nuget Package Manager—>Manage Nuget Packages for Solution…,打开以下界面:

在Browser 标签下输入SignalR,查询到Microsoft.AspNet.SignalR
/p>
找到对应的项目,点击“Install”安装按钮即可引用相关类库,同时应用下载相关js库。
关于SignalR的知识点,可以到官网 http://www.asp.net/signalr 进行深入学习。
3.2 服务端SignalR实现
服务端要向客户端推送UUID,对于UUID唯一标识符,具有重要特性:(1)有时间限制,120秒之内扫码有效;(2)具有一定的状态。对应的声明周期就是:生成—>推送—>状态判断—>手机端扫描—>验证UUID—>状态判断—>销毁等系列过程。
服务端的核心代码将单独建立一个项目去实现:

3.2.1 Nofifier.cs通知类
本类将连接QRCodeHub与SessionTimer
using Microsoft.AspNet.SignalR;namespace TxSms.SingalR { public static class Notifier { private static readonly IHubContext Context = GlobalHost.ConnectionManager.GetHubContext(); public static void SessionTimeOut(string connectionId, int time) { Context.Clients.Client(connectionId).alertClient(time); } public static void SendElapsedTime(string connectionId, int time) { Context.Clients.Client(connectionId).sendElapsedTime(time); } public static void SendQRCodeUUID(string connectionId, string uuid) { Context.Clients.Client(connectionId).sendQRCodeUUID(uuid); } } } 3.2.2 QRCodeHub.cs SignalR核心实现
SignalR的核心代码:
using Microsoft.AspNet.SignalR; using System.Threading.Tasks; namespace TxSms.SingalR { /// /// 二维码推送 /// //[HubName("qrcode")] public class QRCodeHub : Hub { /// /// 给客户端发送时间间隔 /// /// public void SendTimeOutNotice(int time) { Clients.Client(Context.ConnectionId).alertClient(time); } public void CheckElapsedTime(int time) { Clients.Client(Context.ConnectionId).sendElapsedTime(time); } /// /// 发送二维码UUID内容 /// /// public void SendQRCodeUUID(string uuid) { Clients.Client(Context.ConnectionId).sendQRCodeUUID(uuid); } /// /// Called when the connection connects to this hub instance. /// /// A public override Task OnConnected() { SessionTimer.StartTimer(Context.ConnectionId); return base.OnConnected(); } /// /// Called when a connection disconnects from this hub gracefully or due to a timeout. /// /// /// true, if stop was called on the client closing the connection gracefully; /// false, if the connection has been lost for longer than the /// . /// Timeouts can be caused by clients reconnecting to another SignalR server in scaleout. /// /// A public override Task OnDisconnected(bool stopCalled) { SessionTimer.StopTimer(Context.ConnectionId); return base.OnDisconnected(stopCalled); } /// /// Called when the connection reconnects to this hub instance. /// /// A public override Task OnReconnected() { if (!SessionTimer.Timers.ContainsKey(Context.ConnectionId)) { SessionTimer.StartTimer(Context.ConnectionId); } return base.OnReconnected(); } /// /// 重置时钟 /// public void ResetTimer() { SessionTimer timer; if (SessionTimer.Timers.TryGetValue(Context.ConnectionId, out timer)) { timer.ResetTimer(); } else { SessionTimer.StartTimer(Context.ConnectionId); } } /// /// 发送普通消息 /// /// /// public void Send(string name, string message) { Clients.All.addNewMessageToPage(name, message); } } }3.2.3 SessionTimer.cs 对应客户端时钟
对【B】来说,产生一个独立的timer,进行按1s间隔发送消息。
using System;using System.Collections.Concurrent;using System.Timers;namespace TxSms.SingalR{ public class SessionTimer : IDisposable { /// /// 存储客户端对应的Timer /// public static readonly ConcurrentDictionary Timers; private readonly Timer _timer; static SessionTimer() { Timers = new ConcurrentDictionary(); } /// /// 构造函数 /// /// private SessionTimer(string connectionId) { ConnectionId = connectionId; _timer = new Timer { Interval = Utility.ActivityTimerInterval() }; _timer.Elapsed += (s, e) => MonitorElapsedTime(); _timer.Start(); } public int TimeCount { get; set; } /// /// 客户端连接Id /// public string ConnectionId { get; set; } /// /// 启动Timer /// /// public static void StartTimer(string connectionId) { var newTimer = new SessionTimer(connectionId); if (!Timers.TryAdd(connectionId, newTimer)) { newTimer.Dispose(); } } /// /// 停止Timer /// /// public static void StopTimer(string connectionId) { SessionTimer oldTimer; if (Timers.TryRemove(connectionId, out oldTimer)) { oldTimer.Dispose(); } } /// /// 重置Timer /// public void ResetTimer() { TimeCount = 0; _timer.Stop(); _timer.Start(); } public void Dispose() { // Stop might not be necessary since we call Dispose _timer.Stop(); _timer.Dispose(); } /// /// 给客户端发送消息 /// private void MonitorElapsedTime() { Utility.ClearExpiredUUID(); var uuid = Utility.GetUUID(ConnectionId); //if (TimeCount >= Utility.TimerValue()) //{ // StopTimer(ConnectionId); // Notifier.SendQRCodeUUID(ConnectionId, uuid); // Notifier.SessionTimeOut(ConnectionId, TimeCount); //} //else // { Notifier.SendQRCodeUUID(ConnectionId, uuid); Notifier.SendElapsedTime(ConnectionId, TimeCount); //} TimeCount++; if (TimeCount > 1000) { TimeCount = 0; } } }} 3.2.4 Utility.cs 基础配置
满足时钟、获取QRCode等
using TxSms.Actions;namespace TxSms.SingalR { internal class Utility { public static int IntNum = 0; /// /// 时间间隔 /// /// public static int TimerValue() { return 1000; } public static double ActivityTimerInterval() { return 1000.0; } /// /// 获取当前UUID /// /// public static string GetUUID(string connectionId) { try { var model = new QRCodeAction().GetValidModel(connectionId); return model.ToJson(connectionId); } catch { return "ERROR"; } } /// /// 删除过期UUID /// public static void ClearExpiredUUID() { IntNum++; if (IntNum <= 1000) return; new QRCodeAction().ClearExpiredUUID(); IntNum = 0; } }}3.2.5 SignalR在MVC中启动配置
在MVC中,启动项目进行如下配置:
using Microsoft.Owin;using Owin; [assembly: OwinStartup(typeof(TxSms.Web.Startup))]namespace TxSms.Web{ public partial class Startup { public void Configuration(IAppBuilder app) { //启动SignalR app.MapSignalR(); ConfigureAuth(app); } }}3.2.6 其他类库说明
QRCodeAction.cs:维护UUID,创建、保存、状态更改、删除等。
QRModel.cs:UUID实体
所有文件,可在《7、总结与下载》中下载。
3.3 客户端SignalR实现
添加SignalR js库:
两者必须都引用。
调用接口如下:
var codeUUID = ""; $(function () { // Reference the auto-generated proxy for the hub. var qrcode = $.connection.qRCodeHub; // Create a function that the hub can call back to display messages. qrcode.client.addNewMessageToPage = function (name, message) { // Add the message to the page. console.log(message); //jQuery('#divQRCode').qrcode({ width:
相关内容
- asp.net core分块上传文件示例_实用技巧_
- 剖析Asp.Net路由系统实现原理_实用技巧_
- Windows Server 2012 R2 或 2016无法安装.Net 3.5.1_实用技巧_
- asp.net实现XML文件读取数据绑定到DropDownList的方法_实用技巧_
- mvc重定向方式详解_实用技巧_
- ASP.NET Core中使用默认MVC路由的配置_实用技巧_
- Asp.net 中mvc 实现超时弹窗后跳转功能_实用技巧_
- asp.net实现的MVC跨数据库多表联合动态条件查询功能示例_实用技巧_
- .NET实现WebSocket服务端即时通信实例_实用技巧_
- ASP.NET实现MVC中获取当前URL、controller及action的方法_实用技巧_
点击排行
本栏推荐
