【问题标题】:How to persist SignalR connection ID如何保留 SignalR 连接 ID
【发布时间】:2015-12-14 23:00:30
【问题描述】:

我正在尝试构建一个聊天应用程序,其中用户 ID 由他们自动生成的 signalR 连接 ID 表示。在页面刷新时,连接 ID 会在实例化新连接时更改。有没有办法将用户的连接 ID 状态保持到浏览器会话结束(即直到他在客户端结束会话)。

任何指南或文档?真的很有帮助。

我是信号员的新手。所以想知道很多搜索谷歌的东西。从这个网址我得到了一个类似的 sn-p http://kevgriffin.com/maintaining-signalr-connectionids-across-page-instances/

他们说这是可能的。问题是如果我们引用页面,信号器通常会创建一个新的连接 ID。我想防止这种情况,但是如何.......

这个代码sn-p。

public class MyConnectionFactory : IConnectionIdFactory
    {
        public string CreateConnectionId(IRequest request)
        {
            if (request.Cookies["srconnectionid"] != null)
            {
                return request.Cookies["srconnectionid"];
            }

            return Guid.NewGuid().ToString();
        }
    }

$.connection.hub.start().done(function () {
        alert("Connected!");
        var myClientId = $.connection.hub.id;
        setCookie("srconnectionid", myClientId);
    });

    function setCookie(cName, value, exdays) {
        var exdate = new Date();
        exdate.setDate(exdate.getDate() + exdays);
        var c_value = escape(value) + ((exdays == null) ? "" : "; expires=" + exdate.toUTCString());
        document.cookie = cName + "=" + c_value;
    }

我怀疑它是否适用于所有信号器版本?如果不是,那么如何在新版本中处理它,特别是如果页面刷新,则不会生成新的连接 ID。寻找建议。

如果我们使用持久连接类而不是集线器,那么会发生什么.....在这种情况下,如果我们在客户端刷新页面,连接 ID 将保持不变?请指导。 谢谢

【问题讨论】:

    标签: asp.net signalr


    【解决方案1】:

    SignalR 允许您通过他们的IPrincipal.Identity.Name 向用户发送消息。只需使用Clients.User(userName) 而不是Clients.Client(connectionId)。

    如果您由于某种原因无法使用他们的IPrincipal.Identity.Name 与用户联系,您可以创建自己的IUserIdProvider。这是在 SignalR >= 1.0.0 中不再存在的 IConnectionIdFactory 的替代品。

    等效的IUserIdProvider 如下所示:

    public class MyConnectionFactory : IUserIdProvider
    {
        public string GetUserId(IRequest request)
        {
            if (request.Cookies["srconnectionid"] != null)
            {
                return request.Cookies["srconnectionid"];
            }
    
            return Guid.NewGuid().ToString();
        }
    }
    
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var idProvider = new MyConnectionFactory();
            GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider);
    
            app.MapSignalR();
        }
    }
    
    public class MyHub : Hub
    {
        public Task Send(string userName, string message)
        {
            return Clients.User(userName).receive(message);
        }
    }
    

    鉴于此MyConnectionFactory,欺骗用户真的很简单。您可以使用HMAC 使其更安全。

    理想情况下,您只需使用从IRequest.User.Identity.Name 检索用户ID 的default IUserIdProvider。

    【讨论】:

    • 感谢您的回答。我需要使用什么信号器版本来运行您的代码。我正在使用信号器和 VS2010 IDE。那么告诉我你的代码是否适用于 VS2010 版本?
    • Clients.User(userName) 和 Clients.Client(connectionId) 方法有什么区别。用户名可能不是唯一的,但 connectionId 始终是唯一的。那么如果 userName 不是唯一的会发生什么?请指导。谢谢
    • IConnectionIdFactory 在 SignalR 1.0.0 中被删除。 IUserIdProvider 是在 SignalR 2.0.0 中引入的。您的 VS 版本无关紧要。您是正确的,可以是具有相同用户名的多个 SignalR 连接。例如,同一用户可能在多个浏览器选项卡中打开 SignalR 应用程序。在这种情况下,属于具有 userName 的用户的每个连接都将接收使用 Clients.User(userName) 发送给该用户的消息。
    • Clients.User(userName) 和 Clients.Client(connectionId) 方法有什么区别?集线器和客户端是通过连接 ID 映射的,所以不清楚这条线如何工作 Clients.User(userName) ? Clients.User(userName).ClientFunctionName() 如何在正确的客户端触发?你能详细说明一下吗?谢谢
    • 对不起....我需要一个小帮助,如果我使用 IUserIdProvider 那么即使我刷新页面,连接 ID 也会持续存在?您不提供信号器客户端 js 代码。如果可能的话,在此处添加它,以便我可以看到您如何将连接 ID 存储在 cookie 中,并进行设置,因此连接 ID 即使在页面引用时也会保持不变。
    【解决方案2】:

    用户 ID 提供程序不起作用,因为连接 ID 不是来自它。我实现了一个解决方案 (https://weblogs.asp.net/ricardoperes/persisting-signalr-connections-across-page-reloads),它使用存储在会话存储中的伪会话 ID。然后将每个 SignalR 连接 ID 映射到此伪会话 ID。

    【讨论】:

    • 请不要对多个问题发布(几乎)相同的答案。如果它们是重复的,则使用您的接近投票。如果不是,请尝试调整您对这些特定问题的答案。此外,请不要发布仅链接的答案。您可以在此处提供(部分)代码并使用链接作为参考。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多