簡體   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