我终于得到了答案。
有人建议我应该使用非常有效的 ASP NET Identity,但我已经创建了简单的身份验证和用户管理。它不安全,不如 ASP NET Identity 好一半(我仔细研究了一下,并理解了它),但它只是个人项目,而不是生产项目,所以如果它发展了,我可能会切换到 Identity 甚至自己实现一个;) 但事实并非如此。
它需要一点额外的步骤,所以:
-
我需要在 ASP.NET Core 中启用会话,为此我使用了 this article。有了这个,我可以保留我的用户登录并将其提供给 signalR 的用户 ID 提供程序
-
在 .NET 中为 SignalR 添加 cutsom 用户 ID 提供程序:
我需要创建这样的类
public class UserIdProvider : IUserIdProvider
{
public static readonly string SESSION_LOGIN_KEY = "loggedUser";
private readonly IHttpContextAccessor _httpContextAccessor;
public UserIdProvider(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public string GetUserId(HubConnectionContext connection)
{
var session = _httpContextAccessor.HttpContext.Session;
session.TryGetValue(SESSION_LOGIN_KEY, out byte[] loginBA);
if (loginBA == null)
{
return null;
}
return new string(loginBA.Select(b => (char)b).ToArray());
}
}
所以,登录后我可以在Session 中设置登录,所以它变成“状态”变量,并在上面的类中使用它。
另外,需要在 ASP 服务中添加它,如下所示(Startup.ConfigureServices):
services.AddSingleton<IUserIdProvider, UserIdProvider>();
还有一件事,仍然需要设置:在UserIdProvider 中,我们需要通过HttpContext 访问Session。为了使用HttpContext,我们需要像下面这样指定它(也在Startup.ConfigureServices中):
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
将HttpContextAccessor 传递给服务构造函数。
在这一切之后,您可以使用在 Context.UserIdnentifier 中设置的登录名访问 SignalR Hub 中的用户
这也可以向特定用户发送消息,只需传递他们的登录名(前端客户端只需选择用户),如下所示:
public async Task SendMessage(string message, string user)
{
await Clients.User(user).SendAsync("ReceiveMessage", message).ConfigureAwait(false);
}
注意 但是有一个问题。计算机上的浏览器没有持久化会话,我解决了这个问题(也在Startup.ConfigureServices):
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => false; // <~~~~ This needs to be set to false
options.MinimumSameSitePolicy = SameSiteMode.None;
});
没有它,您需要小心使用 cookie,如果您在网站上不接受它们,它将无法工作,因为用户的登录将不会被持久化。