.NET Core SignalR:如何完成基于资源的授权?

时间:2018-11-12 20:45:07

标签: .net-core authorization signalr jwt

我所有的SignalR客户端都使用JWT承载令牌进行连接。我在SignalR [Authorize]中使用了Hub属性。

此令牌包含一个userId,可用于检查用户是否通过资源的users属性(其中包含一个类似以下内容的List<PuppyUserPermission>)对资源进行读取访问:< / p>

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);
    }
}

我会像下面这样(这是比其他任何东西都更多的伪代码,因为我没有使用有效的方法):

[Authorize]
public class PuppyHub : Hub
{
    public async Task SendPuppy(Puppy pup)
    {
        var clients = Puppy.users.Where(u => u.read == true);
        await clients.SendAsync(pup);
    }
}

基本上,我想确保通过SignalR接收Puppy对象的客户端将是该资源上的授权用户。问题是,Clients只是string个客户端ID的列表,我不确定如何将它们与我的Puppy资源上的实际用户联系起来。

如何实现这一目标?

1 个答案:

答案 0 :(得分:1)

从一开始,我就感到答案位于IUserIdProvider中,但是我看不到这对多个用户如何起作用。

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

首先,如下创建您自己的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<IUserIdProvider, MyUserIdProvider >();

现在,当您要从服务器发送事件时,请像往常一样在构造函数中使用DI下拉SignalR Hub的实例:

 private IHubContext<PuppyHub> puppyHub { get; }
 public UsersController(IHubContext<PuppyHub> _puppyHub)
 {
     puppyHub = _puppyHub;
 }

然后,当您要将新的Puppy告诉客户时:

// ... 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);

中提琴!您现在已经使用SignalR完成了基于资源的授权。