基于SignalR的消息推送与二维码扫描登录实现代码
1 概要说明
使用微信扫描登录相信大家都不会陌生吧,二维码与手机结合产生了不同应用场景,基于二维码的应用更是比较广泛。为了满足ios、android客户端与web短信平台的结合,特开发了基于SinglarR消息推送机制的扫描登录。本系统涉及到以下知识点:
SignalR: 这官网,ASP.NET SignalR 是为 ASP.NET 开发人员提供的一个库,可以简化开发人员将实时 Web 功能添加到应用程序的过程。实时 Web 功能是指这样一种功能:当所连接的客户端变得可用时服务器代码可以立即向其推送内容,而不是让服务器等待客户端请求新的数据。
二维码:使用的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的知识点,可以到官网 进行深入学习。
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<QRCodeHub>(); 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 { /// <summary> /// 二维码推送 /// </summary> //[HubName("qrcode")] public class QRCodeHub : Hub { /// <summary> /// 给客户端发送时间间隔 /// </summary> /// <param name="time"> </param> public void SendTimeOutNotice(int time) { Clients.Client(Context.ConnectionId).alertClient(time); } public void CheckElapsedTime(int time) { Clients.Client(Context.ConnectionId).sendElapsedTime(time); } /// <summary> /// 发送二维码UUID内容 /// </summary> /// <param name="uuid"> </param> public void SendQRCodeUUID(string uuid) { Clients.Client(Context.ConnectionId).sendQRCodeUUID(uuid); } /// <summary> /// Called when the connection connects to this hub instance. /// </summary> /// <returns>A <see cref="T:System.Threading.Tasks.Task" /> </returns> public override Task OnConnected() { SessionTimer.StartTimer(Context.ConnectionId); return base.OnConnected(); } /// <summary> /// Called when a connection disconnects from this hub gracefully or due to a timeout. /// </summary> /// <param name="sCalled"> /// true, if s was called on the client closing the connection gracefully; /// false, if the connection has been lost for longer than the /// <see cref="P:Microsoft.AspNet.SignalR.Configuration.IConfigurationManager.DisconnectTimeout" />. /// Timeouts can be caused by clients reconnecting to another SignalR server in scaleout. /// </param> /// <returns>A <see cref="T:System.Threading.Tasks.Task" /> </returns> public override Task OnDisconnected(bool sCalled) { SessionTimer.STimer(Context.ConnectionId); return base.OnDisconnected(sCalled); } /// <summary> /// Called when the connection reconnects to this hub instance. /// </summary> /// <returns>A <see cref="T:System.Threading.Tasks.Task" /> </returns> public override Task OnReconnected() { if (!SessionTimer.Timers.ContainsKey(Context.ConnectionId)) { SessionTimer.StartTimer(Context.ConnectionId); } return base.OnReconnected(); } /// <summary> /// 重置时钟 /// </summary> public void ResetTimer() { SessionTimer timer; if (SessionTimer.Timers.TryGetValue(Context.ConnectionId, out timer)) { timer.ResetTimer(); } else { SessionTimer.StartTimer(Context.ConnectionId); } } /// <summary> /// 发送普通消息 /// </summary> /// <param name="name"> </param> /// <param name="message"> </param> 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 { /// <summary> /// 存储客户端对应的Timer /// </summary> public static readonly ConcurrentDictionary<string, SessionTimer> Timers; private readonly Timer _timer; static SessionTimer() { Timers = new ConcurrentDictionary<string, SessionTimer>(); } /// <summary> /// 构造函数 /// </summary> /// <param name="connectionId"></param> private SessionTimer(string connectionId) { ConnectionId = connectionId; _timer = new Timer { Interval = Utility.ActivityTimerInterval() }; _timer.Elapsed += (s, e) => MonitorElapsedTime(); _timer.Start(); } public int TimeCount { get; set; } /// <summary> /// 客户端连接Id /// </summary> public string ConnectionId { get; set; } /// <summary> /// 启动Timer /// </summary> /// <param name="connectionId"> </param> public static void StartTimer(string connectionId) { var newTimer = new SessionTimer(connectionId); if (!Timers.TryAdd(connectionId, newTimer)) { newTimer.Dispose(); } } /// <summary> /// 停止Timer /// </summary> /// <param name="connectionId"> </param> public static void STimer(string connectionId) { SessionTimer oldTimer; if (Timers.TryRemove(connectionId, out oldTimer)) { oldTimer.Dispose(); } } /// <summary> /// 重置Timer /// </summary> public void ResetTimer() { TimeCount = 0; _timer.S(); _timer.Start(); } public void Dispose() { // S might not be necessary since we call Dispose _timer.S(); _timer.Dispose(); } /// <summary> /// 给客户端发送消息 /// </summary> private void MonitorElapsedTime() { Utility.ClearExpiredUUID(); var uuid = Utility.GetUUID(ConnectionId); //if (TimeCount >= Utility.TimerValue()) //{ // STimer(ConnectionId); // Notifier.SendQRCodeUUID(ConnectionId, uuid); // Notifier.SessionTimeOut(ConnectionId, TimeCount); /
编程语言
- 机械手焊接机器人编程 机械手焊接设备编程
- vb数据库编程实例,vb做数据库
- tiobe世界编程语言排行榜,全球编程语言排行
- 成都java编程培训 成都it编程培训中心
- 编程基础培训,编程基础知识培训
- flash游戏编程基础教程,flash游戏开发教程
- 不会英语能学编程吗 不会英语可以学程序员吗
- 爱心代码编程C语言 爱心代码编程c语言公式
- c语言编程学习入门 c语言编程快速入门
- 西门子plc编程培训 西门子plc编程培训班
- 哪里可以学编程 台州哪里可以学编程
- 少儿编程哪个好 少儿编程哪个品牌好
- 编程是什么意思,图形编程是什么意思
- c语言编程软件下载,c语言编程软件在哪下载
- java编程软件下载,java编程下载手机版
- ug编程培训学校,ug编程培训教程