为什么我无法通过 Web 套接字连接获取 HubCallerContext 用户?
Why I can't get the HubCallerContext user with web sockets connections?
当我使用 WebSockets 时,我无法在服务器上获取 userId
客户代码:
HubConnection = new HubConnectionBuilder().WithUrl(Config.BaseUrl + ApplicationConstants.SignalR.HubUrl, options =>
{
options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets;
options.Headers.Add("Authorization", $"Bearer {NPCompletApp.Token}");
options.AccessTokenProvider = async () => await Task.FromResult(NPCompletApp.Token);
}).WithAutomaticReconnect().Build();
服务器代码:
public override async Task<Task> OnConnectedAsync()
{
ConnectedUserModel connectedUserModel = new ConnectedUserModel()
{
ConnectionId = Context.ConnectionId, UserId = _userManager.GetUserId(Context.User)
};
UserHandler.connectedUsers.Add(connectedUserModel);
var temp = new List<string>();
foreach(ConnectedUserModel connectedUser in UserHandler.connectedUsers)
{
if (!String.IsNullOrEmpty(connectedUserModel.UserId) && temp.Find(x=> x == connectedUserModel.UserId) == null)
{
temp.Add(connectedUserModel.UserId);
await OnConnectAsync(connectedUserModel.UserId);
}
}
return base.OnConnectedAsync();
}
好的是,如果用户断开连接,我可以捕获,但仍然无法知道用户是谁。
服务器代码(断开连接时):
public override async Task<Task> OnDisconnectedAsync(Exception? exception)
{
var connection = UserHandler.connectedUsers.Find(x => x.ConnectionId == Context.ConnectionId);
await OnDisconnectAsync(connection.UserId);
UserHandler.connectedUsers.Remove(connection);
return base.OnDisconnectedAsync(exception);
}
另一方面,当我使用 LongPolling 时,我可以获得 userId,但在断开连接时我无法捕捉到他
客户代码:
HubConnection = new HubConnectionBuilder().WithUrl(Config.BaseUrl + ApplicationConstants.SignalR.HubUrl, options =>
{
options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.LongPolling;
options.Headers.Add("Authorization", $"Bearer {NPCompletApp.Token}");
options.AccessTokenProvider = async () => await Task.FromResult(NPCompletApp.Token);
}).WithAutomaticReconnect().Build();
我该怎么办?我想知道在我的上下文中谁是用户并在他断开连接时抓住他。
在您的服务器上,您必须配置中间件。
这取自一个工作项目...
服务器:
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPostConfigureOptions<JwtBearerOptions>,
ConfigureJwtBearerOptions>());
ConfigureJwtBearerOptions.cs
public class ConfigureJwtBearerOptions : IPostConfigureOptions<JwtBearerOptions>
{
private readonly ChatConfigurations config;
public ConfigureJwtBearerOptions(ChatConfigurations config)
{
this.config = config;
}
public void PostConfigure(string name, JwtBearerOptions options)
{
var originalOnMessageReceived = options.Events.OnMessageReceived;
options.Events.OnMessageReceived = async context =>
{
await originalOnMessageReceived(context);
if (string.IsNullOrEmpty(context.Token)) {
var accessToken = context.Request.Query["access_token"];
var requestPath = context.HttpContext.Request.Path;
var endPoint = $"/{config.EndPoint}";
if (!string.IsNullOrEmpty(accessToken) &&
requestPath.StartsWithSegments(endPoint)) {
context.Token = accessToken;
}
}
};
}
}
在您的客户端中,您还必须配置令牌。
public async ValueTask InitialiseAsync()
{
IsInitialised = false;
hubConnection = CreateHubConnection();
hubConnection.On<string, string>("ReceiveMessage", ReceiveMessageAsync);
....
await hubConnection.StartAsync();
await hubConnection.SendAsync("JoinGroup", roomName);
IsInitialised = true;
}
private HubConnection CreateHubConnection()
{
var endPoint = $"/{config.EndPoint}";
var hubConnection = new HubConnectionBuilder()
.WithUrl(navigationManager.ToAbsoluteUri(endPoint), options =>
{
options.AccessTokenProvider = async () =>
{
var accessTokenResult = await accessTokenProvider.RequestAccessToken();
accessTokenResult.TryGetToken(out var accessToken);
var token = accessToken.Value;
return token;
};
})
.WithAutomaticReconnect()
.Build();
return hubConnection;
}
我的 Hubs OnConnectedAsync
public async override Task OnConnectedAsync()
{
logger.LogDebug("Hub Connection");
await chatService.RegisterConnectionAsync(Context.ConnectionId, Context.UserIdentifier);
await base.OnConnectedAsync();
}
注意:我正在保持与数据库的连接。
我的 Hubs OnDisconnectedAsync
public async override Task OnDisconnectedAsync(Exception exception)
{
logger.LogDebug("Hub Disconnect");
await chatService.RegisterDisconnectAsync(Context.ConnectionId);
await base.OnDisconnectedAsync(exception);
}
一些调试日志:
dbug: OrakTech.ChatServer.Brokers.Loggings.LoggingBroker[0]
Hub Connection
dbug: OrakTech.ChatServer.Brokers.Loggings.LoggingBroker[0]
Hub Connected (r7SJaAMEGs7eovH810H5Xg, c8f81673-d8b3-4e46-80f6-a83b671e6ff1)
dbug: OrakTech.ChatServer.Brokers.Loggings.LoggingBroker[0]
Join Group (TestRoom : r7SJaAMEGs7eovH810H5Xg)
dbug: OrakTech.ChatServer.Brokers.Loggings.LoggingBroker[0]
Hub Disconnect
dbug: OrakTech.ChatServer.Brokers.Loggings.LoggingBroker[0]
Hub Disconnect (r7SJaAMEGs7eovH810H5Xg)
当我使用 WebSockets 时,我无法在服务器上获取 userId
客户代码:
HubConnection = new HubConnectionBuilder().WithUrl(Config.BaseUrl + ApplicationConstants.SignalR.HubUrl, options =>
{
options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets;
options.Headers.Add("Authorization", $"Bearer {NPCompletApp.Token}");
options.AccessTokenProvider = async () => await Task.FromResult(NPCompletApp.Token);
}).WithAutomaticReconnect().Build();
服务器代码:
public override async Task<Task> OnConnectedAsync()
{
ConnectedUserModel connectedUserModel = new ConnectedUserModel()
{
ConnectionId = Context.ConnectionId, UserId = _userManager.GetUserId(Context.User)
};
UserHandler.connectedUsers.Add(connectedUserModel);
var temp = new List<string>();
foreach(ConnectedUserModel connectedUser in UserHandler.connectedUsers)
{
if (!String.IsNullOrEmpty(connectedUserModel.UserId) && temp.Find(x=> x == connectedUserModel.UserId) == null)
{
temp.Add(connectedUserModel.UserId);
await OnConnectAsync(connectedUserModel.UserId);
}
}
return base.OnConnectedAsync();
}
好的是,如果用户断开连接,我可以捕获,但仍然无法知道用户是谁。
服务器代码(断开连接时):
public override async Task<Task> OnDisconnectedAsync(Exception? exception)
{
var connection = UserHandler.connectedUsers.Find(x => x.ConnectionId == Context.ConnectionId);
await OnDisconnectAsync(connection.UserId);
UserHandler.connectedUsers.Remove(connection);
return base.OnDisconnectedAsync(exception);
}
另一方面,当我使用 LongPolling 时,我可以获得 userId,但在断开连接时我无法捕捉到他
客户代码:
HubConnection = new HubConnectionBuilder().WithUrl(Config.BaseUrl + ApplicationConstants.SignalR.HubUrl, options =>
{
options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.LongPolling;
options.Headers.Add("Authorization", $"Bearer {NPCompletApp.Token}");
options.AccessTokenProvider = async () => await Task.FromResult(NPCompletApp.Token);
}).WithAutomaticReconnect().Build();
我该怎么办?我想知道在我的上下文中谁是用户并在他断开连接时抓住他。
在您的服务器上,您必须配置中间件。
这取自一个工作项目...
服务器:
services.TryAddEnumerable(
ServiceDescriptor.Singleton<IPostConfigureOptions<JwtBearerOptions>,
ConfigureJwtBearerOptions>());
ConfigureJwtBearerOptions.cs
public class ConfigureJwtBearerOptions : IPostConfigureOptions<JwtBearerOptions>
{
private readonly ChatConfigurations config;
public ConfigureJwtBearerOptions(ChatConfigurations config)
{
this.config = config;
}
public void PostConfigure(string name, JwtBearerOptions options)
{
var originalOnMessageReceived = options.Events.OnMessageReceived;
options.Events.OnMessageReceived = async context =>
{
await originalOnMessageReceived(context);
if (string.IsNullOrEmpty(context.Token)) {
var accessToken = context.Request.Query["access_token"];
var requestPath = context.HttpContext.Request.Path;
var endPoint = $"/{config.EndPoint}";
if (!string.IsNullOrEmpty(accessToken) &&
requestPath.StartsWithSegments(endPoint)) {
context.Token = accessToken;
}
}
};
}
}
在您的客户端中,您还必须配置令牌。
public async ValueTask InitialiseAsync()
{
IsInitialised = false;
hubConnection = CreateHubConnection();
hubConnection.On<string, string>("ReceiveMessage", ReceiveMessageAsync);
....
await hubConnection.StartAsync();
await hubConnection.SendAsync("JoinGroup", roomName);
IsInitialised = true;
}
private HubConnection CreateHubConnection()
{
var endPoint = $"/{config.EndPoint}";
var hubConnection = new HubConnectionBuilder()
.WithUrl(navigationManager.ToAbsoluteUri(endPoint), options =>
{
options.AccessTokenProvider = async () =>
{
var accessTokenResult = await accessTokenProvider.RequestAccessToken();
accessTokenResult.TryGetToken(out var accessToken);
var token = accessToken.Value;
return token;
};
})
.WithAutomaticReconnect()
.Build();
return hubConnection;
}
我的 Hubs OnConnectedAsync
public async override Task OnConnectedAsync()
{
logger.LogDebug("Hub Connection");
await chatService.RegisterConnectionAsync(Context.ConnectionId, Context.UserIdentifier);
await base.OnConnectedAsync();
}
注意:我正在保持与数据库的连接。
我的 Hubs OnDisconnectedAsync
public async override Task OnDisconnectedAsync(Exception exception)
{
logger.LogDebug("Hub Disconnect");
await chatService.RegisterDisconnectAsync(Context.ConnectionId);
await base.OnDisconnectedAsync(exception);
}
一些调试日志:
dbug: OrakTech.ChatServer.Brokers.Loggings.LoggingBroker[0]
Hub Connection
dbug: OrakTech.ChatServer.Brokers.Loggings.LoggingBroker[0]
Hub Connected (r7SJaAMEGs7eovH810H5Xg, c8f81673-d8b3-4e46-80f6-a83b671e6ff1)
dbug: OrakTech.ChatServer.Brokers.Loggings.LoggingBroker[0]
Join Group (TestRoom : r7SJaAMEGs7eovH810H5Xg)
dbug: OrakTech.ChatServer.Brokers.Loggings.LoggingBroker[0]
Hub Disconnect
dbug: OrakTech.ChatServer.Brokers.Loggings.LoggingBroker[0]
Hub Disconnect (r7SJaAMEGs7eovH810H5Xg)