2015-03-21 1 views
0

У меня есть веб-приложение, которое представляет собой единую установку IIS (это не меняется), но имеет динамический набор поддоменов. У каждого поддомена есть собственные учетные записи пользователей.Изолируйте пользователей в концентраторе signalR по домену

Проблема, с которой я столкнулся, заключается в том, что когда я запускаю signalR на ней, она рассматривает все поддомены как один и тот же домен, поэтому пользователи, у которых только что произошло одно и то же имя пользователя, получат сообщения друг друга.

Это вызывает у меня проблему нарушения безопасности между учетными записями домена.

До сих пор мои лучшие решения для решения этой проблемы имеют разные уровни рисков и проблем.

  1. Каждый пользователь получает свою собственную группу, создавая имя группы с именем поддомена + имя пользователя.
    1. Элемент списка уменьшает риск столкновения, но не удаляет его.
    2. Использование указателя для имени домена и резервирование первых n-символов для указателя снижает риск еще больше, но теперь для каждого пользователя онлайн теперь у меня сформирована группа.
  2. На старте owin разверните новый центр, представляющий каждый домен.
    1. Каждый раз, когда я добавляю субдомен, мне придется перезапустить приложение, чтобы добавить новый концентратор. Прямо сейчас, мне не нужно ничего делать, чтобы добавить поддомены, которые DNS поддерживает подстановочный знак, а заголовок хоста в IIS пуст. Все работает, за исключением отсутствия осведомленности о субдоменах в SignalR.
  3. Создайте собственный класс концентратора, который информирует домен коллекций клиентов, как и все остальные приложения.
    1. Это, по-видимому, самое чистое, но, безусловно, самое трудоемкое время. Он также представляет наибольший риск ошибок, так как мне придется составлять большую коллекцию тестов QA за пределами тестирования модулей TDD.
  4. Последняя опция, не используйте SignalR, создайте собственный API длинного опроса.
    1. Это самый сложный вопрос, поскольку он является самой высокой пропускной способностью и наиболее подверженным процессу. Основной опрос наших целевых пользователей показывает, что они используют браузеры, поддерживающие websocket, поэтому почему мы намеренно увеличиваем пропускную способность или создаем новую задержку.

Чтобы увидеть эту неудачу, просто взять простой чат демо на ASP.NET/SignalR, и запустить его на локальном компьютере под двумя различными браузерами (FF и IE для моих основных тестов), и имеют один вызов http: \ localhost и другой вызов http: \ yourcomputername. Для правильного тестирования вам понадобится IIS, а не IIS Express.

+0

Я закончил отмену этого проекта. По-видимому, только что существующий на сервере концентратор убивал производительность нашего SSRS-зрителя. Хотя я буду читать это, когда у меня будет время. – Brian

ответ

1

Мои 2 цента: создайте собственную реализацию IUserIdProvider, оттуда должно быть легко проверить каждый запрос и сгенерировать уникальный идентификатор пользователя в нескольких доменах, которые вы вернете, таким образом SignalR будет знать, кому связать каждый запрос правильно. Это было бы простое и неинвазивное решение. Вы можете проверить here для более подробной информации.

1

Я знаю, что это немного поздно, однако я также столкнулся с этой проблемой, и с тех пор я решил ее использовать группы, однако я сделал это, чтобы реализовать сам IHub, а затем, когда set Clients называется wrap значение в моей собственной реализации IHubCallerConnectionContext<dynamic>, а затем используйте ключ, чтобы изолировать все вызовы, выполненные с использованием уже доступных методов. Вот пример того, что этот класс выглядел так:

internal class ClientsDatabaseIsolator : IHubCallerConnectionContext<object> 
{ 
    private readonly string _database; 
    private readonly IHubCallerConnectionContext<dynamic> _clients; 

    public ClientsDatabaseIsolator(string database, IHubCallerConnectionContext<dynamic> clients) 
    { 
     if (database == null) throw new ArgumentNullException(nameof(database)); 
     this._database = database; 
     this._clients = clients; 
    } 

    private string PrefixDatabase(string group) 
    { 
     return string.Concat(_database, ".", group); 
    } 

    public dynamic AllExcept(params string[] excludeConnectionIds) 
    { 
     return _clients.Group(_database, excludeConnectionIds); 
    } 

    public dynamic Client(string connectionId) 
    { 
     return _clients.Client(connectionId); 
    } 

    public dynamic Clients(IList<string> connectionIds) 
    { 
     return _clients.Clients(connectionIds); 
    } 

    public dynamic Group(string groupName, params string[] excludeConnectionIds) 
    { 
     return _clients.Group(PrefixDatabase(groupName), excludeConnectionIds); 
    } 

    public dynamic Groups(IList<string> groupNames, params string[] excludeConnectionIds) 
    { 
     return _clients.Groups(groupNames.Select(PrefixDatabase).ToList(), excludeConnectionIds); 
    } 

    public dynamic User(string userId) 
    { 
     return _clients.User(userId); 
    } 

    public dynamic Users(IList<string> userIds) 
    { 
     return _clients.Users(userIds); 
    } 

    public dynamic All 
    { 
     get { return _clients.Group(_database); } 
    } 

    public dynamic OthersInGroup(string groupName) 
    { 
     return _clients.OthersInGroup(PrefixDatabase(groupName)); 
    } 

    public dynamic OthersInGroups(IList<string> groupNames) 
    { 
     return _clients.OthersInGroups(groupNames.Select(PrefixDatabase).ToList()); 
    } 

    public dynamic Caller 
    { 
     get { return _clients.Caller; } 
    } 

    public dynamic CallerState 
    { 
     get { return _clients.CallerState; } 
    } 

    public dynamic Others 
    { 
     get { return _clients.OthersInGroup(_database); } 
    } 
} 

затем в OnConnected добавить подключение к _database группе

сейчас в моей ступице, когда я звоню Clients.All.Send("message"), который будет действительно только отправлять сообщения в группу, указанную когда был создан ClientsDatabaseIsolator, это было бы похоже на вызов Clients.Group(database).Send("message") таким образом, что вам не нужно об этом думать. Я не уверен, что это лучшее решение, но оно сработало для нас.

+0

Я также недавно понял, что у вас будут проблемы при использовании групп, если вы используете мою реализацию. если вы, например, присоединитесь к группе «test» (например: «Groups.Add (Context.ConnectionId,« test »)), когда вы вызываете' Clients.Group («test») ', вы действительно собираетесь отправлять сообщения в группу «database.test», я также обновлю этот ответ на эту работу. – Eluvatar