Я схожие проблемы здесь, как в моем веб-приложении, я использую простую систему аутентификации cookie, которая использует подход стиля AoP для проверки любые контроллеры с атрибутом, затем получит текущий контекст (будь то из статического HttpContext.Current или из целевого объекта вызова в зависимости от типа перехватчика), а затем проверьте, существует ли файл cookie, он содержит правильные данные, а затем, наконец, проверьте токен с db или кешем и т. д.
В любом случае этот подход также может использоваться для Signalr, хотя его бит более длинный, и вы используете инъекцию зависимости.Вы бы в основном обернули вызовы концентратора с требуемым атрибутом, а затем настроили конфигурацию DI/IoC для перехвата этих вызовов, затем либо получите экземпляр хаба в своем перехватчике, либо получите cookie (или ваш собственный механизм аутентификации) из запроса, проверьте все это действует или нет, а если нет, то выкиньте new HttpException("403", "Not authenticated");
, который должен отбросить пользователя и вернуться назад, прежде чем он даже ударит по вашему хаб-методу, таким образом вы можете поместить логику в одном месте (ваш перехватчик или класс перехватчик потребляет), то просто оберните любой метод, который должен использовать эту аутентификацию, используя ваш атрибут.
Я использую Ninject и расширение перехвата, но большинство крупных DI каркасов в эти дни имеют некоторую форму IoC плагин/расширения, такие как Autofac, Виндзор, весной и т.д.
Если вы не были счастливы идти вниз маршрут введения DI и/или AOP в ваш текущий проект, то, возможно, вы могли бы просто создать пользовательский экземпляр хаба, который содержит вашу логику аутентификации, а затем просто использовать это в ваших концентраторах, так что вы все равно будете вручную вызывать некоторую логику аутентификации изнутри каждого хаб метод, который вы хотите защитить, но его меньше кода, так что-то вроде:
public class AuthorisableHub : Hub
{
private ISomeAuthenticationToken GetSomeAuthenticationTokenFromRequest(Request request) // probably a SignalR specific request object
{
// Get your token from the querystring or cookie etc
}
private bool IsAuthenticationTokenValid(ISomeAuthenticationToken token)
{
// Perform some validation, be it simple or db based and return result
}
protected void PerformUserAuthentication()
{
var token = GetSomeAuthenticationTokenFromRequest(Context.Request);
var isRequestValid = IsAuthenticationTokenValid(token);
if(!isRequestValid)
{ throw new HttpException(403, "<Some forbidden message here>"); }
}
}
public class MyFancyPantsHub : AuthorisableHub
{
public void TellAllClientsSomethingSecret(ISecret secret)
{
PerformUserAuthentication();
// Do stuff with the secret as it should have bombed the user out
// before it reaches here if working correctly
}
}
Это не идеально, но будет работать (я думаю), также я уверен, что когда-то я читал, что Hubs снова создаются для каждого запроса, и если это действительно так, вы можете просто поместить эту логику в свой конструктор, если хотите применять аутентификацию для каждого действия внутри концентратора.
Надеюсь, что это поможет или даст вам идеи ... было бы интересно узнать, как вы его решали в конце.
Я реализовал защиту на основе токенов, передав сгенерированный токен пользователя с каждым сигнальным запросом через строку запроса (то есть $ .connection.hub.qs). Клиент получает ключ, который перекрестно ссылается на пользователя, а на сервере я беру токен, а затем загружаю пользователя из перекрестного ref. Он работает, но он довольно уродлив, и я не могу понять, как чисто обеспечить безопасность, не вызывая метод ValidateToken(), который вызывает ошибку. –
Любое обновление по этому вопросу? Вы нашли лучший способ сделать это еще? Я сталкиваюсь с такой же ситуацией. – BowserKingKoopa