Windows Azure: веб-приложение на несколько экземпляров, аутентификация? - PullRequest
2 голосов
/ 25 октября 2011

Существующее веб-приложение, которое я хочу перенести в Windows Azure Cloud, аутентифицирует пользователей следующим образом где-то в (post) authenticaterequest событии:

IPrincipal current = Thread.CurrentPrincipal;
if (current != null && ((IClaimsIdentity)current.Identity).Claims.Count > 0)
{
    IPrincipal result =  AuthManager.CreateGenericPrincipal(current.Identity);
    HttpContext.Current.User = result;
    Thread.CurrentPrincipal = result;
}

Метод CreateGenericPrincipal ищет роли в xml-файле на предмет утверждений и создает новый GenericPrincipal с этими ролями. Страницы, которые требуют аутентификации, просто выполняют

IPrincipal p = Thread.CurrentPrincipal;
p.IsInRole("rolesFromXml");

Это прекрасно работает с одним экземпляром веб-ролей, поскольку нет большой разницы для обычного хостинга IIS. Но будет ли он работать с 2, 3 или 5 экземплярами? Балансировщик нагрузки Azure не является «липким», пользователи могут быть перенаправлены в другой экземпляр при использовании приложения. Не знаю, если Thread.CurrentPrincipal все еще путь.

Здесь я использую идентификацию на основе утверждений. При первом входе пользователя на страницу он перенаправляется в службу маркеров безопасности. До сих пор это происходит только один раз. Было бы неприятно, если бы это происходило несколько раз при использовании нескольких экземпляров.

Спасибо!

Ответы [ 2 ]

2 голосов
/ 25 октября 2011

Обычно происходит то, что вас перенаправляют только один раз, происходит танец перенаправления (пассивное перенаправление), и вы получаете токен. Токен обычно кешируется в cookie в зашифрованном формате. Таким образом, последующие запросы не делают танец перенаправления.

Проблема здесь в том, что, поскольку cookie-файл зашифрован, все серверы в веб-ферме должны иметь ключ шифрования для расшифровки. Из коробки у вас возникнут проблемы с WIF, поскольку по умолчанию используется DPAPI. Этот тип шифрования преднамеренно отличается для каждой машины. Это ломается в облаке.

Что вам нужно сделать, это загрузить сертификат службы как часть вашего развертывания и изменить способ, которым cookie-файл шифруется на что-то, что является дружественным для веб-фермеров. Вот магический код:

private void OnServiceConfigurationCreated(object sender, 
    ServiceConfigurationCreatedEventArgs e)
{
    var sessionTransforms =
        new List<CookieTransform>(
            new CookieTransform[] 
            {
                new DeflateCookieTransform(), 
                new RsaEncryptionCookieTransform(
                  e.ServiceConfiguration.ServiceCertificate),
                new RsaSignatureCookieTransform(
                  e.ServiceConfiguration.ServiceCertificate)  
            });
    var sessionHandler = new 
     SessionSecurityTokenHandler(sessionTransforms.AsReadOnly());
    e.ServiceConfiguration.SecurityTokenHandlers.AddOrReplace(
        sessionHandler);
}

Это настраивает ваш обработчик токена безопасности для использования RSA Encryption с материалом ключа, полученным из установленного сертификата.

В этом примере приложения представлена ​​более подробная информация и информация, иллюстрирующая проблему и решение:

http://msdn.microsoft.com/en-us/library/ff966481.aspx

Дополнительные правки:

В ASP.NET существует конвейер, в котором настроен WIF. Он перехватывает событие аутентификации и извлекает токен из куки и строит ваш IPrincipal так, чтобы последующий код имел это в контексте. Обычно вы не создаете Принципала самостоятельно при использовании STS. Вместо этого, если вам нужно изменить Принципал, вы подключаетесь к конвейеру в WIF и вставляете дополнительные утверждения в утверждение «роль» (фактически пространство имен URI). Затем WIF будет использовать эти утверждения для создания ClaimsPrincipal, который будет содержать такие вещи, как роли и просто работающие компоненты (IsInRole, web.config auth и т. Д.).

Если возможно, лучше, чтобы токен содержал роли в качестве утверждений. Однако это гораздо более длительное обсуждение вокруг «нормализации» претензий на значимые контексты. Помните, что требования, которые вы получаете от IP-STS, соответствуют их собственным условиям, и они могут ничего не значить для вашего приложения. Например, я могу получить от клиента заявление о том, что он входит в группу Adatum \ Managers. Это совершенно бессмысленно для моего приложения, поэтому я обычно заменяю этот токен на тот, который мое приложение понимает, и в процессе преобразует или нормализует утверждения путем сопоставления утверждений (т.е. Adatum \ Managers -> MyApplicationAdminRole). Служба Windows Azure ACS очень пригодна для этой цели (нормализация заявок с разных IP-адресов).

Я бы порекомендовал прочитать книгу Витторио обо всем этом, чтобы получить общие закономерности здесь:

Примечания Эудженио: Добавление к тому, что написал @dunnry, и все правильно. Надлежащим пунктом расширения для дополнения вашего набора претензий в проверяющей стороне (вашем веб-приложении) является использование ClaimsAuthenticationManager . Документы для этого типа здесь . на этой странице есть ссылки на образцы. В этом классе вы читаете роли из XML-файла и добавляете их в ClaimsIdentity. Остальная часть приложения не будет беспокоиться о претензиях и т. Д. (Особенно если вы используете роли, как в вашем случае). Конфигурация RSA для шифрования файлов cookie решает проблему балансировки нагрузки.

1 голос
/ 25 октября 2011

Посмотрите на мой пост, я только что сделал то же самое.

http://therubblecoder.wordpress.com/2011/10/25/wif-and-load-balancing-with-mvc-3/

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

В элементе microsoft.identity в конфигурации вам необходим элемент, который выглядит следующим образом.

<serviceCertificate>
  <certificateReference x509FindType="FindByThumbprint"    findValue="****THUMBPRINT*****" storeLocation="LocalMachine"  storeName="My" />
</serviceCertificate>

Пул приложений также должен получить доступ к этому, иначе он не сможет найти сертификат по отпечатку пальца.

Приведенный выше код будет использовать этот сертификат при работе с токеном.Если у вас нет этой настройки, вы получите исключение нулевой ссылки.

...