我已将 SignalR 添加到我现有的 MVC 项目中,并尝试使用来自 MVC 的相同 ApplicationUserManager 将用户加载到中心上下文中。
连接完成后,我像这样调用一些服务器方法:
var alertsHub = $.connection.monitoringHub;
$(function() {
alertsHub.client.processAlertChange = function (name, alert) {
console.log(alert);
};
//start the connection
$.connection.hub.start().done(function () {
console.log("Connected, transport = " + $.connection.hub.transport.name);
alertsHub.server.subscribeToMonitor();
});
});
在我的 Hub 方法中有一个调用
CurrentUser = ConnectedUsers.GetOrAdd(this.Context.ConnectionId, UserManager.FindByName(this.Context.User.Identity.Name));
UserManager 就是这样的属性
protected static ConcurrentDictionary<string, ApplicationUser> ConnectedUsers = new ConcurrentDictionary<string, ApplicationUser>();
private ApplicationUserManager _userManager;
public ApplicationUserManager UserManager
{
get
{
if (_userManager == null)
{
_userManager = Context.Request.GetHttpContext().GetOwinContext().GetUserManager<ApplicationUserManager>();
}
return _userManager;
}
}
protected ApplicationUser CurrentUser { get; set; }
问题是,当使用 webSockets 传输时,我收到错误“无法访问已处理的对象”
SignalR: webSockets transport connected. Initiating start request.
SignalR: The start request succeeded. Transitioning to the connected state.
SignalR: Now monitoring keep alive with a warning timeout of 13333.333333333332, keep alive timeout of 20000 and disconnecting timeout of 300000
Connected to monitoringHub, transport = webSockets
SignalR: Invoking monitoringhub.SubscribeToMonitor
SignalR: monitoringhub.SubscribeToMonitor failed to execute. Error: Cannot access a disposed object.
Object name: 'ApplicationUserManager'.
但是!当我强制 serverSentEvents 传输时 - 没有错误,一切都很好。为什么?以及如何修复...
我的 Startup.cs
ConfigureAuth(app);
// Any connection or hub wire up and configuration should go here
var hubConfiguration = new HubConfiguration();
hubConfiguration.EnableDetailedErrors = true;
app.MapSignalR("/sr", hubConfiguration);
GlobalHost.HubPipeline.RequireAuthentication();
GlobalHost.Configuration.ConnectionTimeout = TimeSpan.FromSeconds(120);
GlobalHost.Configuration.DisconnectTimeout = TimeSpan.FromSeconds(300);
GlobalHost.Configuration.KeepAlive = TimeSpan.FromSeconds(10);
最佳答案
看起来您使用的是身份验证 token (Bearer 或其他)。默认情况下,SignalR 不会向服务器发送身份验证 token 。所以,上下文是空的。请参阅 Microsoft 文档 https://learn.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-5.0
// Connect, using the token we got.
this.connection = new signalR.HubConnectionBuilder()
.withUrl("/hubs/chat", { accessTokenFactory: () => this.loginToken })
.build();
添加 accessTokenFactory(在客户端)后,SignalR 会将 token 值作为“access_token”包含到 Request.Query 参数中,并且无法将“access_token”名称更改为另一个名称(例如“token”) .因此,您需要实现额外的处理程序或中间件来在后端验证和填充上下文。
context.Request.Query["access_token"]
关于c# - SignalR ApplicationUserManager 在使用 webSockets 传输时被释放,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36056109/