Javascript 保持信号机连接的方法

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现在不可用。但是现在我需要这个连接在聊天室里发送信息 所以这个变量必须“转移”到下一个脚本 因此,在网站上的整个会话中实际保持连接的方法是什么?在服务器端,您可以通过以下方式将消息发送给特定用户: 在客户端,只要启动连接并监听集线器

我正在创建一个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,甚至自己实现一个;)但事实并非如此

它需要一些额外的步骤,因此:

  • 我需要在ASP.NET Core中启用会话,为此我使用了。这样,我就可以持久化我的用户登录,并将其提供给signer的用户ID提供者

  • 正在为.NET中的信号器添加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());
      }
    }
    
    所以,在登录之后,我可以在
    会话中设置login,这样它就变成了“state”变量,并在上面的类中使用它

    此外,还需要将其添加到ASP服务中,如下所示(在
    Startup.ConfigureServices
    中):

    它将
    HttpContextAccessor
    传递给服务构造函数

    在所有这些之后,您可以使用signar
    Hub
    中的用户登录名访问用户,登录名在
    上下文中设置。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;
    });