连接到 SignalR 集线器时将 UserIdentifier 或 User.Identity.Name 设置为 null

cvg*_*cvg 2 signalr signalr-hub signalr.client angular asp.net-core-signalr

我正在尝试使用 Angular 作为客户端应用程序创建一个 .net core 3.0 SignalR 项目。我已经在客户端和服务器之间建立了成功的连接,并向所有连接的客户端发送消息。我打算将消息发送给特定用户而不是所有连接的客户端。为了实现这一目标,我尝试使用 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);

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

客户端/角度代码

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))
  }

Run Code Online (Sandbox Code Playgroud)

每当连接新客户端时,我都可以看到connectionIdbutUserIdentifier的值User.Identity.Name显示为 null。

在此输入图像描述

我不知道为什么会发生这种情况;我是否遗漏了一些东西,或者需要做什么来定义 UserIdentifers?

Ism*_*mar 6

在我看来,您需要为您创建的 Hubs 类指定 [Auhtorize] 属性,并实现 IUserIdProvider,然后在 Startup.cs 类中注册它。

1. 在集线器上执行此操作:

[Authorize]
public class MessageHub : Hub
{
  // Code removed for brevity
}
Run Code Online (Sandbox Code Playgroud)

2. 根据需要实现 UserId 或 Name 或 Email 的 IUserIdProvider

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

           return connection.User.FindFirst("sub").Value;
      }
 }
Run Code Online (Sandbox Code Playgroud)

3.在Startup.cs类中注册Provider

public void ConfigureServices(IServiceCollection services)
{
     services.AddSignalR();
     services.AddSingleton<IUserIdProvider, IdBasedUserIdProvider>();
}
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助您解决您遇到的问题