.net core .NET核心信号器:如何完成基于资源的授权?

.net core .NET核心信号器:如何完成基于资源的授权?,.net-core,authorization,signalr,jwt,.net Core,Authorization,Signalr,Jwt,我所有的信号器客户端都使用JWT承载令牌进行连接。我在信号器集线器中使用[Authorize]属性 此令牌包含一个userId,可用于检查用户是否通过资源的users属性对资源具有读取权限,该属性包含一个类似以下内容的列表: public class PuppyUserPermission { public string userId { get; set; } public bool read { get; set; } public bool write { get;

我所有的信号器客户端都使用JWT承载令牌进行连接。我在信号器
集线器中使用
[Authorize]
属性

此令牌包含一个
userId
,可用于检查用户是否通过资源的
users
属性对资源具有读取权限,该属性包含一个类似以下内容的
列表

public class PuppyUserPermission
{
    public string userId { get; set; }
    public bool read { get; set; }
    public bool write { get; set; }
}
问题是:我如何连接这些点?理想情况下,而不是像

[Authorize]
public class PuppyHub : Hub
{
    public async Task SendPuppy(Puppy pup)
    {
        await Clients.All.SendAsync(pup);
    }
}
我想这样做(这是比其他任何东西都多的伪代码,因为我不使用有效的方法):

基本上,我希望确保通过signar接收
Puppy
对象的客户机是资源上的授权用户。问题是,
客户端
只是一个
字符串
客户端ID的列表,我不知道如何将它们绑定到我的
Puppy
资源上的实际用户


如何实现这一点?

从一开始,我就觉得答案就在这里,但我不知道这对多个用户会起什么作用

我终于找到了答案,但肯定需要清理一下

首先,创建自己的
IUserIdProvider
实现,如下所示:

public class MyUserIdProvider : IUserIdProvider
{
    public string GetUserId(HubConnectionContext connection)
    {
        var username = connection.User.Claims.Where(x => x.Type == "THE_CLAIM_YOU_WANT_TO_USE_TO_IDENTIFY_USERS").First().Value;
        return username;
    }
}
接下来,使用DI注册它:

services.AddSingleton()

现在,当您想要从服务器发送事件时,请在构造函数中使用DI,按照通常的方式下拉SignalR
Hub
的实例:

 private IHubContext<PuppyHub> puppyHub { get; }
 public UsersController(IHubContext<PuppyHub> _puppyHub)
 {
     puppyHub = _puppyHub;
 }
还有维奥拉!现在,您已经使用SignalR完成了基于资源的授权

 private IHubContext<PuppyHub> puppyHub { get; }
 public UsersController(IHubContext<PuppyHub> _puppyHub)
 {
     puppyHub = _puppyHub;
 }
// ... typical controller code
// assume we have a var, puppy, with a list of authorized users

// use System.Linq to get a list of userIds where the user is authorized to read the puppy
var authorizedUsers = (IReadOnlyList<string>)puppy.users.Where(x => x.permissions.read == true).Select(i => i._id).ToList();

// send the new puppy to the authorized users
await puppyHub.Clients.Users(authorizedUsers).SendAsync("SendPuppy", puppy);