有没有办法断开用户与 Signalr 服务器端的连接?
Is there a way to disconnect user from Signlar server side?
我正在构建一个使用 SignalR 传输实时消息的应用程序,我正在徘徊是否有任何方法可以让我在服务器端断开用户连接。
由于 SignalR 处理身份验证的方式,我想断开它们。 Signalr 似乎不检查令牌是否在打开的 websocket 连接内过期(它仅在请求开始时或客户端发送消息时检查)。
另一个解决方案是在给定时间后断开客户端。
目前,我所拥有的用于身份验证的只是在 accessTokenProvider 内部发送的 JWT 令牌。
客户端:
new HubConnectionBuilder()
.withUrl(`${env.APPURL}/hub`, {
skipNegotiation: true,
transport: HttpTransportType.WebSockets,
accessTokenFactory: async () => {
const { token } = store;
return token;
},
})
我在客户端处理这个问题。我的 angular 应用程序使用静默刷新令牌调用来刷新 jwt 令牌并保持用户身份验证。
当我将 SignalR 功能添加到我的应用程序时,我还需要更新活动 SignalR 连接的访问令牌。
经过一些研究,唯一的方法是 'reset' 连接。当您停止并再次启动连接时,SignalR 将使用您通过访问令牌工厂传递给它的最新令牌。
如果你想做这个服务器端,你可以向所有客户端发送一条消息,客户端停止连接并立即重新启动它。
最终,停止连接的代码必须在客户端完成。
-- 更新 --
ASP.NET Core SignalR 在 Hub class 中有 Abort 方法。 (但是在 ASP.NET SignalR 中无法执行此操作。)
使用此 Abort 方法,您可以 运行 以每个连接为基础的逻辑,如果需要停止连接,则:
public void AuthenticateConnection()
{
// Run your logic to determine if connection needs to be stopped
// If connection must be stopped
Context.Abort();
}
尽管这确实会停止连接,但无法提供重新启动它的方法,因此您会陷入客户端永久断开连接的状态。因此,如果您打算更新客户端不记名令牌,那么我不确定这是否适合您。
对于更新 JWT 不记名令牌的用例,我建议在您获取令牌时在客户端设置一个 'refresh-token' 计时器。
如果我登录并且令牌从现在起 15 分钟后过期,我将设置一个 14 分钟的计时器,之后我将刷新令牌以保持用户登录状态。每次成功刷新令牌时,我都会停止并启动连接(传递更新的令牌)。
如果您必须从服务器端执行此操作,一种解决方案是发送断开连接消息和客户端 ID,然后具有该 ID 的客户端将收到消息:
服务器端
Clients.All.SendAsync($"disconnect-{clientId}");
客户端
this.connection.on(
`disconnect-${this.clientId}`, async () => {
await this.connection.stop();
await this.connectionstart();
}
);
我正在构建一个使用 SignalR 传输实时消息的应用程序,我正在徘徊是否有任何方法可以让我在服务器端断开用户连接。
由于 SignalR 处理身份验证的方式,我想断开它们。 Signalr 似乎不检查令牌是否在打开的 websocket 连接内过期(它仅在请求开始时或客户端发送消息时检查)。
另一个解决方案是在给定时间后断开客户端。
目前,我所拥有的用于身份验证的只是在 accessTokenProvider 内部发送的 JWT 令牌。
客户端:
new HubConnectionBuilder()
.withUrl(`${env.APPURL}/hub`, {
skipNegotiation: true,
transport: HttpTransportType.WebSockets,
accessTokenFactory: async () => {
const { token } = store;
return token;
},
})
我在客户端处理这个问题。我的 angular 应用程序使用静默刷新令牌调用来刷新 jwt 令牌并保持用户身份验证。
当我将 SignalR 功能添加到我的应用程序时,我还需要更新活动 SignalR 连接的访问令牌。 经过一些研究,唯一的方法是 'reset' 连接。当您停止并再次启动连接时,SignalR 将使用您通过访问令牌工厂传递给它的最新令牌。
如果你想做这个服务器端,你可以向所有客户端发送一条消息,客户端停止连接并立即重新启动它。
最终,停止连接的代码必须在客户端完成。
-- 更新 --
ASP.NET Core SignalR 在 Hub class 中有 Abort 方法。 (但是在 ASP.NET SignalR 中无法执行此操作。)
使用此 Abort 方法,您可以 运行 以每个连接为基础的逻辑,如果需要停止连接,则:
public void AuthenticateConnection()
{
// Run your logic to determine if connection needs to be stopped
// If connection must be stopped
Context.Abort();
}
尽管这确实会停止连接,但无法提供重新启动它的方法,因此您会陷入客户端永久断开连接的状态。因此,如果您打算更新客户端不记名令牌,那么我不确定这是否适合您。
对于更新 JWT 不记名令牌的用例,我建议在您获取令牌时在客户端设置一个 'refresh-token' 计时器。
如果我登录并且令牌从现在起 15 分钟后过期,我将设置一个 14 分钟的计时器,之后我将刷新令牌以保持用户登录状态。每次成功刷新令牌时,我都会停止并启动连接(传递更新的令牌)。
如果您必须从服务器端执行此操作,一种解决方案是发送断开连接消息和客户端 ID,然后具有该 ID 的客户端将收到消息:
服务器端
Clients.All.SendAsync($"disconnect-{clientId}");
客户端
this.connection.on(
`disconnect-${this.clientId}`, async () => {
await this.connection.stop();
await this.connectionstart();
}
);