Способы сохранения соединения SignalR - PullRequest
1 голос
/ 29 марта 2020

Я создаю веб-приложение, которое позволяет пользователям общаться с так называемым чатом.

Чтобы включить такое общение, я использую библиотеку SignalR. Я создаю соединение при первом посещении моей страницы (главной страницы). Таким образом, код JS, который создает соединение, создает переменную, используемую для настройки соединения.

Затем пользователь входит в комнату чата, которая представляет собой другую страницу, поэтому загружаются новые JS и т. Д. c. Тот, который содержал переменную соединения, теперь недоступен. Но теперь мне нужно это соединение для отправки сообщений в моей комнате чата.

Так что эта переменная должна быть "передана" следующим скриптам.

Итак, как бы на самом деле сохранить соединение через весь сеанс на сайте ?

Ответы [ 2 ]

2 голосов
/ 30 марта 2020

На стороне сервера вы можете отправить сообщение указанному c пользователю через идентификатор пользователя :

var user = await _userManager.GetUserAsync(Context.User);

await Clients.User(user.Id).SendCoreAsync("msg", new object[] { user.Id, user.Email });

На стороне клиента, когда соединение установлено и hub msg прослушивается, пользователь получит сообщение:

connection.on('msg', function (...data) {
    console.log('data:', data);
});

Отправляя сообщения через идентификаторы пользователя, вам не нужно заботиться о том, где находится целевой пользователь.


public class ChatHub : Hub
{
    private IUserManager<ApplicationUser> _userManager;

    public ChatHub(UserManager<ApplicationUser> userManager)
    {
        _userManager = userManager;
    }

    public async Task GetInfo()
    {
        var user = await _userManager.GetUserAsync(Context.User);

        await Clients.User(user.Id).SendCoreAsync("msg", new object[] { user.Id, user.Email });
    }
}
1 голос
/ 31 марта 2020

Наконец-то я получил свой ответ.

Было предложено использовать ASP NET Удостоверение, которое очень допустимо, но я уже создал простую аутентификацию и управление пользователями. Это небезопасно и наполовину хорошо, как ASP NET Идентичность (я обдумал это и обдумал), но это всего лишь личный проект, а не производственный, поэтому, если он будет развиваться, я могу переключиться на Идентичность или даже реализовать сам;) Но это не тот случай.

Это потребовало немного дополнительных шагов, поэтому:

  1. Мне нужно было включить сеансы в ASP. NET Core, я использовал эту статью для этой цели. Имея это, я могу сохранить свой логин пользователя и предоставить его поставщику идентификаторов пользователей для signalR

  2. Добавление поставщика идентификаторов пользователя cutsom для SignalR в. NET:

Мне нужно было создать такой класс

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, чтобы он стал переменной "state", и использовать его в вышеприведенном классе.

Кроме того, нужно добавить его в ASP сервисах, как показано ниже (в Startup.ConfigureServices):

services.AddSingleton<IUserIdProvider, UserIdProvider>();

Также есть одна вещь, которую еще нужно установить: в UserIdProvider нам нужно получить доступ от Session до HttpContext. Чтобы использовать HttpContext, нам нужно указать его, как показано ниже (также в Startup.ConfigureServices):

services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

, который передает HttpContextAccessor конструкторам serices.

После всего этого, Вы можете получить доступ к пользователям в SignalR Hub с помощью их логинов, которые установлены в Context.UserIdnentifier

Это также позволяет отправлять сообщения указанному c пользователю, просто передавая его логин (клиент внешнего интерфейса просто выбирает пользователя) , как показано ниже:

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, если вы не принимаете их на сайт, он не будет работать, так как логин пользователя не будет сохранен.

...