断开客户端与服务器端信号器的连接

Posted

技术标签:

【中文标题】断开客户端与服务器端信号器的连接【英文标题】:disconnect client from server side signalr 【发布时间】:2013-03-31 03:23:00 【问题描述】:

我将 SignalR 1 与带有表单身份验证的 MVC4 C# Web 应用程序一起使用。 我的布局页面中有一段 javascript 代码:

$(documnet).ready(function()
       connect to hub code ...
)

我想断开用户与集线器的连接,并在他登录并验证成功后再次开始连接。 我想从我的帐户控制器和方法中的服务器端执行此操作:

public ActionResult LogOn(LoginModel model, string returnUrl)

    if (ModelState.IsValid)
    
        if (System.Web.Security.Membership.ValidateUser(model.UserName, model.Password))
        
            FormsAuthentication.SetAuthCookie(model.UserName, false);
            ....here , disconnect from hub
            ....to make the user reconnect     

我想这样做的原因是,如果用户在登录后更改为经过身份验证并且连接仍然存在,SignalR 会引发错误。错误是:

连接 ID 格式不正确。

【问题讨论】:

【参考方案1】:

您无法从服务器停止和启动 SignalR 连接。您需要致电

$.connection.hub.stop(); //on the client before the user attempts to log on and then call 
$.connection.hub.start(); //after the log on attempt has completed.

【讨论】:

我调用“$.connectino.hub.start();”在每个文档就绪状态..是否可以调用“$.connection.hub.stop();”之前? 当用户连接到集线器时,您必须从客户端获取它,并将其存储起来以便能够与任何新连接进行比较,这也将防止模拟攻击。跨度> 如果员工刚刚被解雇并且需要撤销访问权限会怎样?我需要能够断开任何打开的 signalR 会话。必须有办法。【参考方案2】:

您可以按照您的要求执行操作的一种方法是在您的客户端上编写一个断开连接事件,服务器可以通过 SignalR 调用该事件。也许有点像这样:

myHub.client.serverOrderedDisconnect = function (value) 
    $.connection.hub.stop();
;

然后,在服务器上,是这样的:

Clients.Client(Context.ConnectionId).serverOrderedDisconnect();

【讨论】:

但是如何从“LogOn”操作中的服务器端代码获取 Context.ConnectionId ?【参考方案3】:

如果有人还在寻找解决方案(SignalR 2.4.1 版):

GlobalHost.DependencyResolver.Resolve<ITransportHeartbeat>().GetConnections().First(c => c.ConnectionId == "YourId").Disconnect();

【讨论】:

你在aspnetcore中是怎么做的? 对不起,我只用过asp.net【参考方案4】:

尝试通过 javascript 控制一切。下面是一个注销的例子,登录也是类似的。

来自http://www.asp.net/signalr/overview/security/introduction-to-security:

如果用户的身份验证状态在活​​动连接时发生更改 存在,用户将收到一条错误消息,指出“用户身份 在活动 SignalR 连接期间无法更改。”在这种情况下,您的 应用程序应重新连接到服务器以确保 连接 id 和用户名是协调的。例如,如果您的 应用程序允许用户在活动连接时注销 存在,连接的用户名将不再匹配名称 为下一个请求传入。你会想要停止 在用户注销之前连接,然后重新启动它。

但是,重要的是要注意大多数应用程序不需要 手动停止和启动连接。如果您的应用程序 注销后将用户重定向到单独的页面,例如 Web 窗体应用程序或 MVC 应用程序中的默认行为,或 注销后刷新当前页面,活动连接为 自动断开连接,无需任何额外操作。

以下示例显示了如何在以下情况下停止和启动连接 用户状态已更改。

<script type="text/javascript">
$(function () 
    var chat = $.connection.sampleHub;
    $.connection.hub.start().done(function () 
        $('#logoutbutton').click(function () 
            chat.connection.stop();
            $.ajax(
                url: "Services/SampleWebService.svc/LogOut",
                type: "POST"
            ).done(function () 
                chat.connection.start();
            );
        );
    );
);

【讨论】:

【参考方案5】:

试试这个:

public ActionResult LogOn(LoginModel model, string returnUrl) 
    if (ModelState.IsValid) 
        if (System.Web.Security.Membership.ValidateUser(model.UserName, model.Password)) 
            FormsAuthentication.SetAuthCookie(model.UserName, false);
            connection.Stop();
        

假设您的连接句柄是connection。挑战在于在 Action Method 中访问 connection 对象的句柄。

【讨论】:

但是如何从“LogOn”操作中的服务器端代码中获取“连接”对象? 好问题。没想到这一点。除非您将其添加到会话中,否则它可能不会很容易获得,这似乎是错误的......【参考方案6】:

您可以在 .Net Core 中直接通过 hub 上下文中止()连接

Context.Abort();

看下面的方法

https://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.signalr.hubcallercontext.abort

【讨论】:

【参考方案7】:

将以下函数复制并粘贴到您的 Hub 中

Use HttpContext.Current.Response.End();

强制客户端在您的集线器中断开连接

【讨论】:

抛开语法和表达问题不谈,此解决方案是否存在任何技术问题会导致投票失败?

以上是关于断开客户端与服务器端信号器的连接的主要内容,如果未能解决你的问题,请参考以下文章

open62541 客户端断开连接时的 OPC UA 堆栈服务器端回调

命名管道:服务器端如何知道客户端已断开连接?

QT server服务端如何判断客户端断开连接

socket编程中,服务器如何检测到客户端网络连接的断开.比如说客户端的网线断掉了,从服务端如何能检测到呢l

unity客户端自动断开连接

C++ SOCKET在客户端不正常断开的时候如何重新监听。