Отправка сообщения конкретному пользователю через signalr

Я пытаюсь использовать нового поставщика идентификаторов пользователей, указанного в signalr 2, для отправки сообщений конкретному пользователю. Когда я вызываю метод Clients.All, я вижу, что это работает, поскольку мой код javascript вызывается с сервера, а пользовательский интерфейс создает ожидаемый текст для моего тестового примера. Однако, когда я переключаюсь на Clients.User, клиентский код никогда не вызывается с сервера. Я следил за кодом, приведенным в этом примере: SignalR - отправка сообщения определенному пользователю с помощью (IUserIdProvider) * NEW 2.0.0 *.

NotificationHub.cs:

public class NotificationHub : Hub
{
    [Authorize]
    public void NotifyUser(string userId, int message)
    {
        Clients.User(userId).DispatchMessage(message);
    }

    public override Task OnConnected()
    {
        return base.OnConnected();
    }

    public override Task OnDisconnected(bool stopCalled)
    {
        return base.OnDisconnected(stopCalled);
    }

    public override Task OnReconnected()
    {
        return base.OnReconnected();
    }
}

IUserIdProvider.cs:

public class UserIdProvider : IUserIdProvider
{
    MemberService _memberService;
    public UserIdProvider()
    {
    }

    public string GetUserId(IRequest request)
    {
        long UserId = 0;

        if (request.User != null && request.User.Identity != null &&
            request.User.Identity.Name != null)
        {
            var currenUser = Task.Run(() => _memberService.FindByUserName(request.User.Identity.Name)).Result;
            UserId = currenUser.UserId;
        }

        return UserId.ToString();
    }
}

Startup.cs

    HttpConfiguration config = GlobalConfiguration.Configuration;

        config.Routes.MapHttpRoute(
            "Default2",
            "api/{controller}/{action}/{id}",
            new { id = RouteParameter.Optional });

        config.Routes.MapHttpRoute(
            "DefaultApi2",
            "api/{controller}/{id}",
            new { id = RouteParameter.Optional });

        app.Map("/signalr", map =>
        {
            map.UseCors(CorsOptions.AllowAll);

            var idProvider = new UserIdProvider();

            GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => idProvider); 

            map.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
            {
                Provider = new QueryStringOAuthBearerAuthenticationProvider()
            });

            var hubConfiguration = new HubConfiguration
            {
            };
            map.RunSignalR(hubConfiguration);
        });

        app.MapSignalR();

QuerstringOAuthBearerAuthenticationProvider:

public class QueryStringOAuthBearerAuthenticationProvider
: OAuthBearerAuthenticationProvider
{
    public override Task RequestToken(OAuthRequestTokenContext context)
    {
        if (context == null) throw new ArgumentNullException("context");

        // try to find bearer token in a cookie 
        // (by default OAuthBearerAuthenticationHandler 
        // only checks Authorization header)

        var tokenCookie = context.OwinContext.Request.Cookies["BearerToken"];
        if (!string.IsNullOrEmpty(tokenCookie))
            context.Token = tokenCookie;
        return Task.FromResult<object>(null);
    }

}

Нужно ли мне самому сопоставлять пользователя с подключениями с помощью IUserIdProvider через OnConnected, OnDisconnected и т. Д. Или это происходит автоматически за кулисами? Кто-то не прав в моем опубликованном коде, что тоже может быть проблемой? Я запускаю signalr из той же среды, что и мои сервисы web api rest, не знаю, имеет ли это значение, и использую настройку токена носителя по умолчанию, которую использует веб-api.


person user1790300    schedule 26.07.2016    source источник


Ответы (1)


Вам было бы намного проще создать группу на основе идентификатора подключения подключающегося клиента в событии onConnected и транслировать в группу, которая соответствует подключенному идентификатору, таким образом, если клиент отключается, когда они повторно подключаются, они просто будут принадлежать новую группу себе. Если, конечно, вы не обязаны иметь аутентифицированного пользователя.

person Kelso Sharp    schedule 26.07.2016
comment
Да, у меня должны быть аутентифицированные пользователи, и в настоящее время я использую токены аутентификации, переданные в файлах cookie из соединения сигнализатора, и настраиваемый поставщик, чтобы принять токен аутентификации вместе с IUserProvider. - person user1790300; 27.07.2016
comment
Кроме того, мне нужно расширить это на другие возможности, такие как определение того, кто находится в сети, общение между друзьями и т.д. Похоже, там будет отключение, если кто-то просто закроет свой браузер, не выходя из системы. - person user1790300; 27.07.2016
comment
Вы смотрели учебник по добавлению аутентификации в приложения для сигнализации? asp.net/signalr/overview/security/hub-authorization - person Kelso Sharp; 27.07.2016