[英]Custom Authorization using signalr PersistentConnection with websockets transport
[英]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"]
您可以嘗試以下步驟:
使用 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.