С самого начала у меня было чувство, что ответ лежит в 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.