【发布时间】:2019-11-09 14:04:45
【问题描述】:
我已将 SignalR 引入到我的 ASP.NET Core 2 项目中,但在使用我通常在控制器中使用的 scoped 服务时遇到了一些问题。我觉得问题可能是由于 HTTP 请求、websocket 和集线器之间的生命周期不同。
对于每个 HTTP 请求,中间件都会读取 Authorization 令牌并更新请求的范围服务 (IUser) 上的一些属性(例如 id、声明等)。我在所有控制器中都使用此服务,没有任何问题。为了让它与 SignalR 一起使用,我发送了一个 access_token 查询参数,并预先使用了其他一些 middleware 将此查询参数添加为可以正常工作的标头。
当我尝试访问 SignalR 集线器中的 IUser 服务时,就会出现问题。在构建集线器时,注入的IUser 没有设置任何属性,尽管/hub 请求的中间件只是设置了它们。
如果我将服务设置为单例,那么它可以工作,但IUser 的持续时间不应超过单个请求。
我应该如何为特定 SignalR 连接设置IUser?
// Startup.cs - User has several settable properties
services.AddScoped<IUser, User>();
// User Middleware
public class UserMiddleware
{
private readonly RequestDelegate _next;
public UserMiddleware(RequestDelegate next)
{
_next = next;
}
public Task Invoke(HttpContext context)
{
// retrieve service for this request
var user = context.RequestServices.GetService<IUser>();
// set some properties on the User from auth token
// e.g. User.Id = 1;
return _next(context);
}
}
[Authorize(Roles = Claim.Names.Read)]
public class MyHub : Hub
{
private readonly IUser _user;
public MyHub(IUser user)
{
// user that gets injected has null properties
_user = user;
}
public async Task Foo()
{
// do work with the _user credentials
}
}
public class DownloadController : Controller
{
private readonly IUser _user;
public DownloadController(IUser user)
{
// user gets injected and has properties set
_user = user;
}
}
【问题讨论】:
-
由于该中心旨在与所有注册客户进行交互,而不仅仅是一个特定用户,因此使用某种全局范围的“用户”的想法没有多大意义。您在这里真正想要实现的目标是什么?
-
@ChrisPratt 对,但是每次方法调用都会创建一个新的集线器实例,对吧?我正在尝试在需要经过身份验证的用户的服务器端集线器方法中进行一些调用。我可以让集线器方法将用户作为参数,但我认为使用中间件会更好。
-
this.Context.User属性存在于Hub基类中,所以我不认为用我自己的IUser类尝试类似的东西是不合理的。
标签: c# asp.net asp.net-core .net-core signalr