Получение UserIdentifier или User.Identity.Name как null при подключении к концентратору SignalR

Я пытаюсь создать проект SignalR .net core 3.0 с Angular в качестве клиентского приложения. Я установил успешное соединение между клиентом и сервером и отправляю сообщения всем подключенным клиентам. Я намерен отправлять сообщения конкретному пользователю, а не всем подключенным клиентам. Для этого я пытаюсь работать с ConnectionId, UserIdentifier и User.Identity.Name.

Мой серверный код/концентратор сообщений

namespace SignalR_server
{
    public class MessageHub : Hub
    {
        public static ConcurrentDictionary<string, string> MyUsers = new ConcurrentDictionary<string, string>();

        public override Task OnConnectedAsync()
        {
            string name = Context.User.Identity.Name;
            MyUsers.TryAdd( Context.ConnectionId,name);
            return base.OnConnectedAsync();
        }

        public override Task OnDisconnectedAsync(Exception exception)
        {
            string garbage;
            MyUsers.TryRemove(Context.ConnectionId, out garbage);
            return base.OnDisconnectedAsync(exception);
        }

        public void Send(string msg)
        {
            string strMessage = string.Empty;

            Clients.All.SendAsync("transfermessage",strMessage);
        }

        public string GetConnectionID()
        {
            return Context.ConnectionId;
        }

        public string GetUserIdentifier()
        {
            return Context.UserIdentifier;
        }

        public string GetUserName()
        {
            return Context.User.Identity.Name;
        }

        public Task SendPrivateMessage(string user, string message)
        {
            return Clients.Users(user).SendAsync("transfermessage1", message);

        }
    }
}

Клиентская сторона/код Angular

public startConnection = () => {
    this.hubConnection = new signalR.HubConnectionBuilder()
                            .withUrl('https://localhost:44363/message',{
                              skipNegotiation: true,
                              transport: signalR.HttpTransportType.WebSockets
                            })
                            .build();

    this.hubConnection
        .start()
        .then(() => {
          console.log('Connection Started')
          console.log('Connection ID: ')
          console.log(this.hubConnection.invoke("GetConnectionID"))
          console.log('User Identifier: ')
          console.log(this.hubConnection.invoke("GetUserIdentifier"))
          console.log('User Name: ')
          console.log(this.hubConnection.invoke("GetUserName"))
          // console.log(this.hubConnection.invoke("SendPrivateMessage","Myuser","test message"))
      })
        .catch(err => console.log('Error while connecting: ' + err))
  }

Всякий раз, когда подключается новый клиент, я вижу значение для connectionId, но UserIdentifier, User.Identity.Name оказывается нулевым.

введите здесь описание изображения

Я не уверен, почему это происходит; я что-то упустил или что-то нужно сделать, чтобы определить UserIdentifers?


person cvg    schedule 19.07.2020    source источник
comment
почему вопрос заминусован?   -  person cvg    schedule 19.07.2020
comment
вы решили это?   -  person Ismail Umar    schedule 04.08.2020
comment
Не решил, но я думаю, что для использования UserIdentifiers потребуются авторизации. Я использовал группы вместо пользователей для моего варианта использования   -  person cvg    schedule 05.08.2020
comment
Да, авторизация требуется для использования идентификаторов пользователей и всего остального. Однако вам необходимо реализовать IUserIdProvuder, чтобы получить доступ к идентификаторам.   -  person Ismail Umar    schedule 05.08.2020
comment
Скоро выложу способ   -  person Ismail Umar    schedule 05.08.2020
comment
Какой метод аутентификации вы используете? Токены JWT?   -  person Jamie Rees    schedule 05.08.2020


Ответы (2)


На мой взгляд, вам нужно указать атрибут [Auhtorize] для класса Hubs, который вы создаете, а также реализовать IUserIdProvider, а затем зарегистрировать его в классе Startup.cs.

<сильный>1. Сделайте это в Хабе:

[Authorize]
public class MessageHub : Hub
{
  // Code removed for brevity
}

<сильный>2. Реализуйте IUserIdProvider для UserId, имени или адреса электронной почты по своему усмотрению

public class IdBasedUserIdProvider : IUserIdProvider
 {
      public string GetUserId(HubConnectionContext connection)
      {
           //TODO: Implement USERID Mapper Here
           //throw new NotImplementedException();

           return connection.User.FindFirst("sub").Value;
      }
 }

<сильный>3. Зарегистрируйте поставщика в классе Startup.cs

public void ConfigureServices(IServiceCollection services)
{
     services.AddSignalR();
     services.AddSingleton<IUserIdProvider, IdBasedUserIdProvider>();
}

Я надеюсь, что это поможет вам решить проблему, с которой вы столкнулись

person Ismail Umar    schedule 05.08.2020

добавьте атрибут [Authorize] в public class MessageHub : Hub, теперь класс должен быть

[Authorize]
public class MessageHub : Hub
person Emmanuel Ogoma    schedule 23.07.2020