Javascript 保持信号机连接的方法
我正在创建一个web应用程序,让用户可以通过所谓的聊天进行通信 为了实现这种通信,我使用信号器库。我在第一次访问我的页面(主页)时创建连接。因此,创建连接的JS代码创建用于配置连接的变量 然后用户进入聊天室,这是另一个页面,因此加载了新的JS等。保存连接变量的那个JS现在不可用。但是现在我需要这个连接在聊天室里发送信息 所以这个变量必须“转移”到下一个脚本Javascript 保持信号机连接的方法,javascript,c#,asp.net-core,signalr,asp.net-core-signalr,Javascript,C#,Asp.net Core,Signalr,Asp.net Core Signalr,我正在创建一个web应用程序,让用户可以通过所谓的聊天进行通信 为了实现这种通信,我使用信号器库。我在第一次访问我的页面(主页)时创建连接。因此,创建连接的JS代码创建用于配置连接的变量 然后用户进入聊天室,这是另一个页面,因此加载了新的JS等。保存连接变量的那个JS现在不可用。但是现在我需要这个连接在聊天室里发送信息 所以这个变量必须“转移”到下一个脚本 因此,在网站上的整个会话中实际保持连接的方法是什么?在服务器端,您可以通过以下方式将消息发送给特定用户: 在客户端,只要启动连接并监听集线器
因此,在网站上的整个会话中实际保持连接的方法是什么?在服务器端,您可以通过以下方式将消息发送给特定用户: 在客户端,只要启动连接并监听集线器
msg
,用户就会收到以下消息:
connection.on('msg', function (...data) {
console.log('data:', data);
});
通过用户id发送消息,您无需关心目标用户在哪里
公共类聊天中心:中心
{
私人IUserManager\u用户管理器;
公共聊天中心(用户管理器用户管理器)
{
_userManager=userManager;
}
公共异步任务GetInfo()
{
var user=await\u userManager.GetUserAsync(Context.user);
等待Clients.User(User.Id).SendCoreAsync(“msg”,新对象[]{User.Id,User.Email});
}
}
我终于得到了答案
有人建议我应该使用ASP NET标识,这是非常有效的,但我已经创建了简单的身份验证和用户管理。它不安全,只有ASP NET Identity的一半好(我仔细查看了它,并仔细考虑了它),但它只是个人项目,而不是生产项目,所以如果它发展起来,我可能会切换到Identity,甚至自己实现一个;)但事实并非如此
它需要一些额外的步骤,因此:
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());
}
}
所以,在登录之后,我可以在会话中设置login,这样它就变成了“state”变量,并在上面的类中使用它
此外,还需要将其添加到ASP服务中,如下所示(在Startup.ConfigureServices
中):
它将HttpContextAccessor
传递给服务构造函数
在所有这些之后,您可以使用signarHub
中的用户登录名访问用户,登录名在上下文中设置。useridnFinifier
这还允许向特定用户发送消息,只需传递他们的登录名(前端客户端只选择用户),如下所示:
public async Task SendMessage(string message, string user)
{
await Clients.User(user).SendAsync("ReceiveMessage", message).ConfigureAwait(false);
}
注意但有一个问题。计算机上的浏览器没有持久化会话,我通过以下方法解决了这一问题(也是在Startup.ConfigureServices
):
services.Configure(选项=>
{
//此lambda确定给定请求是否需要非必要cookie的用户同意。
options.checkApprovementRequired=context=>false;//每个连接点的连接都是唯一的,您无法将它们传输到新页面。请查看SignalR中的组。根据用户的用户ID(而不是连接)将用户放入名为“Lobble”的组中当他们登录时。如果他们进入聊天室,即使是在另一个页面上,也将他们放入名为“聊天室xxx”的组中。只要您有一个有效的客户端方法,无论消息在哪个页面上,都可以将其发送到该组。谢谢,很有趣。但是您从哪里获得了\u userManager
实例?它是什么类型?@MichałTurczyn抱歉,我已经更新了我的答案。您可以通过中心构造函数将\u userManager
用作服务。别忘了通过调用启动
classI来启用用户管理器
服务。我找到了答案,谢谢。我创建了自己的自定义身份服务:)再次感谢,但我使用了cutsom身份提供程序而不是ASP身份(我已经自己管理用户)谢谢你的回答,但最终我还是克服了:)
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());
}
}
services.AddSingleton<IUserIdProvider, UserIdProvider>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
public async Task SendMessage(string message, string user)
{
await Clients.User(user).SendAsync("ReceiveMessage", message).ConfigureAwait(false);
}
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;
});