Подтвердить что ты не робот

Защита вызовов SignalR

Я использую клиент SignalR Javascript и ASP.NET ServiceHost. Мне нужно, чтобы концентраторы SignalR и обратные вызовы были доступны только для входа в систему. Я также должен иметь возможность получить личность текущего пользователя, зарегистрированного в Hub, используя FormsIdentity из HttpContext.Current.User.

  • Как защитить концентратор, чтобы только аутентифицированные пользователи могли использовать SignalR?
  • Как получить идентификатор текущего пользователя из Hub?
4b9b3361

Ответ 1

Вы должны использовать this.Context.User.Identity, который доступен от концентратора. См. родственный вопрос

РЕДАКТИРОВАТЬ: Чтобы остановить не прошедших проверку пользователей:

public void ThisMethodRequiresAuthentication()
{
  if(!this.Context.User.Identity.IsAuthenticated)
  {
    // possible send a message back to the client (and show the result to the user)
    this.Clients.SendUnauthenticatedMessage("You don't have the correct permissions for this action.");
    return;
  }

  // user is authenticated continue
}

ИЗМЕНИТЬ № 2: Это может быть лучше, просто верните сообщение

 public string ThisMethodRequiresAuthentication()
    {
      if(!this.Context.User.Identity.IsAuthenticated)
      {
        // possible send a message back to the client (and show the result to the user)
        return "You don't have the correct permissions for this action.");

       // EDIT: or throw the 403 exception (like in the answer from Jared Kells (+1 from me for his answer), which I actually like better than the string)
       throw new HttpException(403, "Forbidden");
      }

      // user is authenticated continue

      return "success";
    }

Ответ 2

Вы можете заблокировать URL-адрес SignalR, используя событие PostAuthenticateRequest на вашем HttpApplication. Добавьте в свой файл Global.asax.cs следующее:

Это блокирует запросы, которые не используют "https" или не аутентифицируются.

public override void Init()
{
    PostAuthenticateRequest += OnPostAuthenticateRequest; 
}

private void OnPostAuthenticateRequest(object sender, EventArgs eventArgs)
{
    if (Context.Request.Path.StartsWith("/signalr", StringComparison.OrdinalIgnoreCase))            
    {
        if(Context.Request.Url.Scheme != "https")
        {
            throw new HttpException(403, "Forbidden");
        }

        if (!Context.User.Identity.IsAuthenticated)
        {
            throw new HttpException(403, "Forbidden");
        }
    }            
}

Внутри вашего концентратора вы можете получить доступ к текущему пользователю через объект Context.

Context.User.Identity.Name

Ответ 3

Для части 1. вашего вопроса вы можете использовать аннотации, как показано ниже (это работало с SignalR 1.1):

[Authorize]
public class MyHub : Hub
{
    public void MarkFilled(int id)
    {
        Clients.All.Filled(id);
    }
    public void MarkUnFilled(int id)
    {
        Clients.All.UnFilled(id);
    }
}

Ответ 4

Что-то не хватает в других ответах - это возможность использовать SignalR, созданный в пользовательских классах auth. Фактическая документация SignalR по этой теме ужасна, но я оставил комментарий в нижней части страницы, где подробно описывается, как это сделать (Аутентификация и авторизация для концентраторов SignalR).

В основном вы переопределяете класс предоставленного SignalR AuthorizeAttribute

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class CustomAuthAttribute : AuthorizeAttribute

Затем вы украшаете свои хабы с помощью [CustomAuth] над объявлением класса. Затем вы можете переопределить следующие методы для обработки auth:

bool AuthorizeHubConnection(HubDescriptor hubDesc, IRequest request);
bool AuthorizeHubMethodInvocation(IHubIncomingInvokerContext hubContext, bool appliesToMethod);

Поскольку я на серверах IIS и имею пользовательскую схему auth, я просто возвращаю true из метода AuthorizeHubConnection, потому что в моем Auth HttpModule я уже аутентифицирую /signalr/connect и/signalr/повторно подключаю вызовы и сохраняю данные пользователя в элемент HttpContext. Таким образом, модуль обрабатывает аутентификацию при первом вызове соединения SignalR (стандартный HTTP-вызов, который инициирует соединение веб-сокета).

Чтобы разрешить вызовы по определенным методам хаба, я проверяю имена методов на разрешения, сохраненные в HttpContext (это тот же HttpContext, сохраненный из первоначального запроса на соединение) и возвращает true или false на основании того, имеет ли пользователь разрешение на вызов определенного метода.

В вашем случае вы, возможно, сможете использовать метод AuthorizeHubConnection и украсить ваши хаб-методы определенными ролями, потому что похоже, что вы используете стандартизованную систему идентификации, но если что-то не работает правильно, вы всегда можете вернуться к грубая сила с помощью промежуточного продукта HttpModule (или OWIN) и поиск контекстных данных при последующих вызовах веб-рассылки с помощью AuthorizeHubMethodInvocation.