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

Простое преобразование претензий и кэширование w/windows authentication

В течение последних нескольких дней я читал об основах идентификации Windows и о том, как он так хорош и гибкий и построен прямо в .net 4.5. Несмотря на то, что вы перешли десятки apis, сообщений в блогах, инструкции и т.д., Я не могу на всю жизнь работать с простой реализацией.

Я использую только проверку подлинности Windows, и я могу получить основную информацию и просмотреть утверждения, которые приходят с ней (это то, где каждый пример, кажется, заканчивается). Однако я хочу затем преобразовать их в полезные утверждения и кэшировать результаты, чтобы преобразование не выполнялось ни по одному запросу.

В моем web.config у меня есть:

  <configSections>
    <section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
    <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
  </configSections>

  <system.identityModel>
    <identityConfiguration>
      <claimsAuthenticationManager type="SecurityProj.MyClaimsTransformationModule,SecurityProj" />
      <claimsAuthorizationManager type="SecurityProj.MyClaimsAuthorizationManager,SecurityProj" />
    </identityConfiguration>
  </system.identityModel>

Однако диспетчер аутентификации никогда не вызывается. Единственный способ, с помощью которого я могу сделать это, - добавить:

protected void Application_PostAuthenticateRequest()
{
    ClaimsPrincipal currentPrincipal = ClaimsPrincipal.Current;
    ClaimsTransformationModule customClaimsTransformer = new MyClaimsTransformationModule();
    ClaimsPrincipal tranformedClaimsPrincipal = customClaimsTransformer.Authenticate(string.Empty, currentPrincipal);
    HttpContext.Current.User = tranformedClaimsPrincipal;
}

В файл global.asax.cs. Он работает по первому запросу, но после этого я получаю после этого "Безопасный дескриптор закрытых" ошибок и не знаю, что его вызывает. Очевидно, что это не правильный способ сделать это, и кто-нибудь знает, что такое лучшая или просто работающая практика? Это просто для проверки подлинности Windows, мне не нужно ничего сложнее, чем это.

Для кэширования я пытался использовать:

        SessionSecurityToken token = FederatedAuthentication.SessionAuthenticationModule
            .CreateSessionSecurityToken(
            currentPrincipal,
            "Security test",
            System.DateTime.UtcNow,
            System.DateTime.UtcNow.AddHours(1),
            true);

        if (FederatedAuthentication.SessionAuthenticationModule != null &&
            FederatedAuthentication.SessionAuthenticationModule.ContainsSessionTokenCookie(HttpContext.Current.Request.Cookies))
        {
            return;
        }
        FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(token);

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

Любая помощь будет оценена по достоинству. Просто нужно, чтобы поиск/преобразование вызывался и набор файлов cookie, спасибо.

4b9b3361

Ответ 1

Сейчас у меня все работает, вот как я это делал:

На этой странице: http://msdn.microsoft.com/en-us/library/ee517293.aspx Был ключевым пунктом:

Если вы хотите, чтобы ваши заявки на использование приложений RP, но у вас нет STS (например, RP использует проверку подлинности с помощью форм или встроенную проверку подлинности Windows), вы можете использовать модуль ClaimsPrincipalHttpModule. Этот модуль находится в вашем приложении HTTP-конвейер и перехватывает информацию аутентификации. Он генерирует IClaimsPrincipal для каждого пользователя на основе имени пользователя, членов группы и другой информации аутентификации. ClaimsPrincipalHttpModule должен быть вставлен в конец конвейера <httpModules>, который является первым элементом в разделе <modules> <system.webServer> в IIS 7.

И эта страница:

http://leastprivilege.com/2012/04/04/identity-in-net-4-5part-2-claims-transformation-in-asp-net-beta-1/

Дает вам весь класс. Теперь добавьте этот класс в web.config:

<modules>
  <add name="ClaimsTransformationHttpModule" type="TestSecurity.ClaimsTransformationHttpModule" />
</modules>

Теперь он вызовет преобразование, и я смогу удалить метод проверки подлинности post в global.asax.

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

private void CreateSession(ClaimsPrincipal transformedPrincipal)
{
    SessionSecurityToken sessionSecurityToken = new SessionSecurityToken(transformedPrincipal, TimeSpan.FromHours(8));
    FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionSecurityToken);
}

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

Наконец, за безопасную ошибку, которую я продолжал получать. Я не совсем уверен в этой причине, но я обнаружил, что если я изменил принципала, который будет передан в Authenticate, а затем вернет его (это то, что он показывает в msdn), тогда ошибка будет отображаться во всех последующих запросах. Однако, если я создал и вернул новый принципал, это не произойдет. Это также оказывается полезным для отказа от претензий, которые вам не нужны.

List<Claim> newClaims = new List<Claim>();

var keeper = ((ClaimsIdentity)incomingPrincipal.Identity).Claims.First(c =>
    c.Type == ClaimTypes.Name);
newClaims.Add(keeper);

ClaimsIdentity ci = new ClaimsIdentity(newClaims, "Negotiate");

return new ClaimsPrincipal(ci);

Итак, теперь я могу проверять подлинность Windows, вводить пользовательские заявки и кэшировать их с помощью файла cookie. Надеюсь, это поможет любому, кто пытается сделать то же самое, и если я не буду делать что-то правильно, дайте мне знать.

Ответ 2

Этот ответ призван дать дополнительные разъяснения по поводу ответа Джона выше, после нескольких неудачных попыток решить некоторые подобные проблемы.

1. ClaimsPrincipalHttpModule

Как выяснил Джон, если вы используете Windows Auth или Forms Auth, ASP.NET не будет автоматически вызывать ваш ClaimsAuthenticationManager (это не федеративный сценарий). Вы должны сделать это самостоятельно после того, как ASP.NET выполнила аутентификацию пользователя. Использование модуля ClaimsPrincipalHttpModule, который раньше был частью IdentityModel, эффективно обеспечит это.

Однако будьте осторожны с использованием этого модуля. Он был удален по какой-то причине. Моя теория о том, почему она была удалена из IdentityModel, заключается в том, что она не играет хорошо, если вы размещаете службы WCF в своем приложении ASP.NET и имеете aspNetCompatibilityEnabled = true. Это приведет к поломке вашей проверки подлинности WCF (модуль будет выполняться перед конвейером WCF, и мой опыт в том, что ваши клиенты WCF больше не смогут правильно аутентифицироваться - я это подтвердил при использовании Windows Auth).

Если вы размещаете службы WCF в этом сценарии, вы должны как-то убедиться, что ClaimsAuthenticationManager вызывается только для запросов, не связанных с WCF. Для запросов WCF вам кажется, что вам нужно полагаться на конвейер WCF (<serviceCredentials useIdentityConfiguration="true" />). Самое простое решение - просто отключить aspNetCompatibilityEnabled. Если это не вариант, вы не должны использовать ClaimsPrincipalHttpModule, но должны каким-то образом проверить входящий запрос и только вызвать ClaimsAuthenticationManager, если запрос не предназначен для WCF.

2. Ошибка безопасного обращения (ObjectDisposedException)

Это происходит, если вы создаете SessionSecurityToken, основанный на WindowsIdentity. Модуль SessionAuthenticationModule имеет специальную логику для обработки заявлений WindowsIdentity, прочитанных с SessionSecurityToken, и попытается повторно связать WindowsIdentity с использованием данных, которые более недействительны. (Я не уверен в обстоятельствах, в которых он будет работать, но он постоянно проваливался во всех сценариях, которые я тестировал). Таким образом, как пояснил Джон, урок состоит в том, что при попытке использовать WIF с Windows auth SessionSecurityTokens не следует создавать из WindowsPrincipal (или, вернее, WindowsIdentity). Любой другой тип преобразованных ClaimsPrincipal должен быть хорошим.