• SignalR系列续集[系列6:使用自己的连接ID]


    目录

    SignalR系列目录

    前言

    老规矩,前言~,在此先道个歉,之前的1-5对很多细节问题都讲的不是很详细,也有很多人在QQ或者博客问我一些问题

    所以,特开了这个续集.. - -, 讲一些大家在开发中遇到的问题和一些解决方案,今天就来说说经常被问到的,如何使用自己定义的连接ID.

    之前我们说过,Signalr提供了唯一的连接ID 获取方法:Context.ConnectionId,

    那么怎么自己定义这个东西呢? (废话一堆 - - ,),进入主题:

    首先,其实在Signalr的前期版本是可以直接自定义Context.ConnectionId,

    使用老版本的可以自行查看IConnectionIdGenerator, IConnectionIdFactory 这两个接口.

    所以特意说明一下,本博客这里的代码,只适用于Signalr2.0以上版本

    代码环境

    开发工具:VS2013   数据库:SQL2008 R2   SignalR版本:2.2

    正文开始

    其实在2.0的版本中,SignalR团队为了安全性,已经完全去除了自定义Context.ConnectionId的接口,但是相应的开放了相对安全的IUserIdProvider

    废话不多说,直接上代码:

    首先帐户登陆的代码:

    其实就是很传统的登陆代码..把一些用户信息写入到Cookie中而已.黄色为重点

        public class UserController : ApiController
        {
            [HttpGet]
            public object Login(string name,string pwd)
            {
               UserInfoBLL bll = new UserInfoBLL();
               if (CacheHelper.Get(name) == null)
               {
                   var userinfo = bll.LoginUser(name, pwd);
                  
                   if (userinfo != null)
                   {
    
                       var context = HttpContext.Current;
                       //帐户信息写入Cookie,自行加密
                       context.Response.Cookies.Add(new HttpCookie(UserEnum.INFO) { Value = JsonConvert.SerializeObject(userinfo) });
    //唯一的登陆ID,作为连接ID context.Response.Cookies.Add(new HttpCookie(UserEnum.SignalRID) { Value = userinfo.LoginName });

    return new { State=true,Message="登陆成功!"}; } else { return new { State=false,Message="帐户或密码输入错误!"}; } } else { return new { State=false,Message="该帐户已经登陆!"}; } } }

    接下来实现IUserIdProvider:

        public class MyUserFactory : IUserIdProvider
        {
    
            public string GetUserId(IRequest request)
            {
                if (request.GetHttpContext().Request.Cookies[UserEnum.SignalRID] != null)
                {
                    return request.GetHttpContext().Request.Cookies[UserEnum.SignalRID].Value;
                }
                return "";
               // return Guid.NewGuid().ToString();
            }
        }

    以上代码是创建一个MyUserFactory类,继承自IUserIdProvider,实现IUserIdProvider的抽象方法GetUserId

    这里的ID我们从Cookies中获取,细心的人应该已经发现了,有个IRequest的参数,所以原则上你可以使用IRequest的各种属性比如QS..你随意..(注:Session暂时无法使用,原因未知)

    接下来,重点来了..

    在Starup中,把我们自定义的MyUserFactory注入到回话设置中..

    代码如下(黄色为重点):

     public class Startup
        {
            public void Configuration(IAppBuilder app)
            {
                // 有关如何配置应用程序的详细信息,请访问 http://go.microsoft.com/fwlink/?LinkID=316888
    
                //重点,将MyUserFactory注入
                var userIdProvider = new MyUserFactory();
                GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => userIdProvider);

    //设置Webapi var config = new HttpConfiguration(); config.Routes.MapHttpRoute(name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional }); System.Web.HttpContext.Current.SetSessionStateBehavior(System.Web.SessionState.SessionStateBehavior.Required); app.UseWebApi(config); app.MapSignalR(); } }

    接下来在Hub中添加代码如下:

                /// <summary>
                /// 获取连接ID,你可以写成自己的扩展方法,或设置成属性,自行定义
                /// </summary>
                /// <returns></returns>
                public string GetSignalrID()
                {
                    if (Context.Request.GetHttpContext().Request.Cookies[UserEnum.SignalRID] != null)
                    {
                        return Context.Request.GetHttpContext().Request.Cookies[UserEnum.SignalRID].Value;
                    }
                    return "";
                }
                //编写发送信息的方法
                public void SendMessage(string message)
                {
    
                    string id = Context.ConnectionId;
                    string username = Context.User.Identity.Name;
                    var userinfo = JsonConvert.DeserializeObject<UserInfo>(Context.Request.GetHttpContext().Request.Cookies[UserEnum.INFO].Value);
                     var Message = new
                            {
                                name = userinfo.UserName,
                                loadname = userinfo.LoginName,
                                picurl = userinfo.UserPicUrl,
                                time = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
                                message = message
                            };
                           
                            Clients.User(GetSignalrID()).broadcastMessage(Message);
                }

    说明:重点是标黄色的地方,看过我之前文章的都知道,之前我们的对指定连接对象发送数据,写法为: Clients.Client("连接ID").客户端方法,

    这里我们换成了Clients.User("自定义ID"),这样就完成了整个使用自己的连接ID的替换工作.

    写在最后

    SignalR确实是一个很好用的东西,无奈国内资料确实很少,有问题可以向我反馈,我会尽量在国外的站上找相关的资料整理成博客,希望SignalR发展的越来越好!

  • 相关阅读:
    常用 Git 命令清单
    谈谈关于PHP的代码安全相关的一些致命知识
    九个Console命令,让 JS 调试更简单
    有趣的博客小工具
    利用fputcsv导出数据备份数据
    IT小天博客APP版本
    七牛云存储文件批量下载工具使用教程
    Mysql的常见几种错误:1045,1044
    我是一个线程
    两行代码快速创建一个iOS主流UI框架
  • 原文地址:https://www.cnblogs.com/GuZhenYin/p/4744786.html
Copyright © 2020-2023  润新知