繁体   English   中英

SignalR ApplicationUserManager 在使用 webSockets 传输时被释放

[英]SignalR ApplicationUserManager is disposed while using webSockets transport

我已将 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 传输时 - 没有错误并且一切正常。 为什么? 以及如何修复它...

我的启动.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);

看起来您使用了身份验证令牌(Bearer 或其他东西)。 默认情况下,SignalR 不会向服务器发送身份验证令牌。 所以, Context 是空的。 请参阅https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-5.0 上的Microsoft 文档

    // Connect, using the token we got.
this.connection = new signalR.HubConnectionBuilder()
    .withUrl("/hubs/chat", { accessTokenFactory: () => this.loginToken })
    .build();

添加 accessTokenFactory(在客户端)后,SignalR 会将令牌值作为“access_token”包含在 Request.Query 参数中,并且不可能将“access_token”名称更改为其他名称(例如“令牌”)。 因此,您需要实现一个额外的处理程序或中间件来在后端进行身份验证和填充 Context。

context.Request.Query["access_token"]

您可以尝试以下步骤:

  1. 在 Fiddler 中打开流式传输。
  2. 如果您的 SignalR 传输是 WebSockets,则在 Fiddler 开启时请求可能需要几秒钟才能通过。

使用 WebSockets SignalR 连接,初始 tcp 连接升级为 ws 连接。 UserManager 上下文在 Hub 连接升级和初始化后被释放。

我建议使用 OAuth Bearer Token 方法。 不是在每个 SignalR 方法中调用 this.Context.User.Identity.Name,而是从承载令牌中获取 UserName。

Microsoft 文档显示了一个示例: Bearer token authentication

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM