注销后如何中止连接 (SignalR)?如何更改 SignOutAsync 方法以中止连接?
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
[HttpPost("SignIn")]
[AllowAnonymous]
public async Task<IActionResult> SignInAsync([FromBody] User user)
{
if (user == null)
{
return BadRequest();
}
// User verification by user.Email and user.Password ...
if (verification == true)
{
var claims = new List<Claim> { new Claim(type: ClaimTypes.NameIdentifier, value: user.Email) };
var principal = new ClaimsPrincipal(new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme));
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal);
return Ok();
}
return Unauthorized();
}
[HttpDelete("SignOut")]
[Authorize]
public async Task SignOutAsync(IHubContext<Hubs.TestHub> hubContext)
{
if (hubContext != null)
{
var nameIdentifier = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (!string.IsNullOrWhiteSpace(nameIdentifier))
{
await hubContext.Clients.User(nameIdentifier).SendAsync("TestHubNotify", $"Sign Out: {nameIdentifier}!");
// ???
// How do I Abort connections for user (ClaimTypes.NameIdentifier)?
// ???
}
}
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
}
SignInAsync方法验证用户数据(电子邮件和密码)。如果检查成功,用户会收到 cookie。
SignOutAsync 方法向所有用户连接发送消息。接下来,需要以某种方式中止所有用户连接。但如何做到这一点呢?然后cookies被删除。
GlobalHost
包含在ASP.NET SignalR
中,但在ASP.NET Core
中已被移除,因此服务器无法直接调用该方法来中断连接。我们需要调用客户端自定义的ForceDisconnect
方法并使用connection.stop();中断连接。
AuthController.cs
[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
private readonly IHubContext<TestHub> _hubContext;
private readonly IConnectionManager _connectionManager;
public AuthController(IHubContext<TestHub> hubContext, IConnectionManager connectionManager)
{
_hubContext = hubContext;
_connectionManager = connectionManager;
}
[HttpDelete("SignOut")]
[Authorize]
public async Task<IActionResult> SignOutAsync()
{
// get userid
var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (string.IsNullOrEmpty(userId))
{
return BadRequest("User identifier is missing.");
}
// get user connections by userid
var connections = _connectionManager.GetConnections(userId);
foreach (var connectionId in connections)
{
// call frontend method
await _hubContext.Clients.Client(connectionId).SendAsync("ForceDisconnect");
}
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Ok();
}
}
前端
connection.on("ForceDisconnect", function () {
console.log("connection abort");
connection.stop();
});
欲了解更多详情,您可以在这里查看我的源代码。
我需要说明的是,这个方法是非常安全的。无论什么场景,如果单个客户端通过浏览器中的脚本执行代码,最多只会中断该客户端的连接,不会影响其他客户端。