ClaimsAuthenticationManager параллельно с RoleManagerModule

Я смешиваю классическую настройку безопасности Membership / RoleManager с новым WIF 4.5 API для целей тестирования. Я реализовал два класса, для которых установлены точки останова:

public class CustomAuthenticationManager : ClaimsAuthenticationManager
    {
        public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
        {
// Breakpoint here is hit 1st
            if (!incomingPrincipal.Identity.IsAuthenticated)
            {
                return base.Authenticate(resourceName, incomingPrincipal);
            }
            return TransformPrincipal(incomingPrincipal);
        }

        private ClaimsPrincipal TransformPrincipal(ClaimsPrincipal incomingPrincipal)
        {
            // this breakpoint is hit last
            ClaimsIdentity newIdentity = new ClaimsIdentity("Custom");
            newIdentity.AddClaims(incomingPrincipal.Claims);
            // I add some additional claims
            ClaimsPrincipal newPrincipal = new ClaimsPrincipal(newIdentity);
            return newPrincipal;
        }
    }

public class CustomRoleProvider : RoleProvider
{
    public override string[] GetRolesForUser(string username)
    {
        // breakpoint here is hit 2nd
        if(username == "me") return new string [] { "Lead", "Developer" };
        return new string[] {};
    }

    #region Not implemented

    // bunch of not implemented methods

    #endregion
}

Теперь результат в порядке, я получаю смешанный ClaimsPrincipal, который имеет как утверждение Name, так и утверждения роли и утверждения, которые я добавил в метод TransformPrincipal.

Однако точки останова отладки достигаются в совершенно странном порядке:

1) Сначала достигается точка останова в начале метода аутентификации

2) Точка останова в начале GetRolesForUser достигается второй

3) остановка в начале TransformPrincipal выполняется последней.

Это просто проблема Visual Studio или есть небольшая вероятность того, что проверка подлинности может завершиться до вызова GetRolesForUser?

Как RoleManagerModule и ClaimsAuthenticationManager работают в конвейере? Параллельно или идет последовательный порядок? Может ли смешивание двух составлять проблемы?

РЕДАКТИРОВАТЬ:

void Application_PostAuthenticateRequest(object sender, EventArgs e)
        {
            ClaimsPrincipal transformedPrincipal = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager.Authenticate(null, ClaimsPrincipal.Current);

            Thread.CurrentPrincipal = transformedPrincipal;
            HttpContext.Current.User = transformedPrincipal;
        }

РЕДАКТИРОВАТЬ:

<membership defaultProvider="CustomMembershipProvider">
  <providers>
    <add name="CustomMembershipProvider" type="Tests.CustomMembershipProvider" />
  </providers>
</membership>
<roleManager enabled="true" defaultProvider="CustomRoleProvider">
  <providers>
    <add name="CustomRoleProvider" type="Tests.CustomRoleProvider" />
  </providers>
</roleManager>


<authentication mode="Forms">
      <forms loginUrl="~/Account/Login" timeout="2880" />
    </authentication>

<system.identityModel>
    <identityConfiguration>
      <claimsAuthenticationManager type="Tests.CustomAuthenticationManager, Tests"/>
    </identityConfiguration>
  </system.identityModel>

person Admir Tuzović    schedule 26.11.2013    source источник
comment
Когда вы входите в ClaimsAuthenticationManager - у вас есть RolePrincipal. IIRC, происходит некоторая ленивая загрузка, которая объясняет, почему GetRolesForUser вызывается где-то посередине. Я бы вообще сбросил RoleManager и просто добавил роли в authNmanager.   -  person leastprivilege    schedule 27.11.2013
comment
Отличный момент, Доминик, принципалом, который передается в метод Authenticate, действительно является RolePrincipal. Означает ли это, что RoleManagerModule создает принципала раньше в конвейере (до ClaimsAuthenticationManager), но утверждения ролей добавляются позже параллельно? Или они извлекаются только тогда, когда к ним обращаются (т.е. когда я преобразую RolePrincipal в свой принципал и перебираю существующие утверждения роли)?   -  person Admir Tuzović    schedule 28.11.2013
comment
Я думаю, что они извлекаются при доступе. Довольно грязно. Я полностью удалил модуль диспетчера ролей.   -  person leastprivilege    schedule 28.11.2013
comment
Это то, что я планирую сделать в конечном итоге, я просто тестировал вещи, когда столкнулся с этим. Спасибо за помощь :)   -  person Admir Tuzović    schedule 28.11.2013


Ответы (1)


Эти двое не предназначены для совместного использования. Управление ролями SAM подавляет управление ролями аутентификации форм, и, как я подозреваю, ваш поставщик ролей просто включен в web.config.

Я не тестировал это в версии 4.5, но не думаю, что это изменилось. В 4.0 диспетчер аутентификации запускается только, если пользователь еще не прошел аутентификацию или текущий пользователь установлен с другим модулем аутентификации. Последнее может произойти неожиданно, если вы создадите как файлы cookie, так и файлы cookie форм и файлы cookie sam. Взгляните на мою запись в блоге об этом

http://www.wiktorzychla.com/2012/09/sessionauthenticationmodule-and-dynamic.html

Хотя я не знаю, почему точка останова при аутентификации попадает первой, SAM заметит, что ваш пользователь RolePrincipal с FormsIdentity, и попытается сделать из этого ClaimsPrincipal, а затем вызовет диспетчер аутентификации.

Изменить: после всего, что вы предоставили, у меня все еще есть небольшая проблема с заказом. Хотя Доминик подозревает, что роли загружаются лениво, я не могу подтвердить это, перекомпилировав BCL. Скорее, RolePrincipal, кажется, охотно добавляет утверждения ролей в конструктор (внутренний метод AttachRoleClaims в классе RolePrincipal).

Независимо от того, как я смотрю на это, я считаю, что GetRolesForUser должен быть вызван первым, поскольку это ClaimsPrincipal.Current передается Authenticate.

Если ваш RoleProvider заранее создаст RolePrincipal, будет вызываться AttachRoleClaims, а роли будут перечислены с RoleProvider.GetRolesForUser.

Если ваш RoleProvider не создает RolePrincipal заранее, ClaimsPrincipal.Current будет, и это приведет к тому же пути выполнения.

Edit2: я нашел возможного виновника, это метод RoleClaimProvider::Claims, который используется внутри AttachRoleClaims. Это реализовано лениво с yield, что означает, что до тех пор, пока кто-то не перечислит утверждения ролей, они не будут созданы. Этот «кто-то» - ваш код из TransformPrincipal:

     ClaimsIdentity newIdentity = new ClaimsIdentity("Custom");
     /* this forces the enumeration */
     newIdentity.AddClaims(incomingPrincipal.Claims);

Однако это также будет означать, что GetRolesForUser будет вызываться последним из TransformPrincipal.

person Wiktor Zychla    schedule 26.11.2013
comment
Я не использую SessionAuthenticationModule, только ClaimsAuthenticationManager. - person Admir Tuzović; 27.11.2013
comment
Конечно, это возможно, но тогда в вашем вопросе не хватает подробностей о том, как вы их вызываете, о диспетчере заявок и поставщике ролей. Вы спрашиваете, как они работают в конвейере, но вы не описали КАКОЙ конвейер (ваш собственный, встроенный, какой, веб или нет). - person Wiktor Zychla; 27.11.2013
comment
Ладно, это моя проблема. В основном я позволяю RoleManagerModule использовать RoleProvider, определяя ‹roleManager› в web.config. Когда дело доходит до ClaimsAuthenticationManager, я вручную вызываю метод аутентификации в Application_PostAuthenticateRequest. - person Admir Tuzović; 27.11.2013
comment
Можете ли вы показать код, который вызывает Authenticate? У меня есть теория о том, почему вы видите методы, вызываемые в этом конкретном порядке, но есть некоторые упущенные моменты, которые я хотел бы заполнить, проверив, что вы на самом деле делаете. - person Wiktor Zychla; 27.11.2013
comment
Я отредактировал свой исходный пост и добавил код в Application_PostAuthenticateRequest. - person Admir Tuzović; 28.11.2013
comment
Отредактировал свой ответ, но я хотел бы увидеть вашу настройку web.config в отношении аутентификации / авторизации и федеративного удостоверения. Тогда я смогу воссоздать ваш сценарий и отладить его. - person Wiktor Zychla; 28.11.2013
comment
Я скину web.config сегодня вместе с RoleProvider, следите за обновлениями. Это действительно проблема, которую стоит изучить. - person Admir Tuzović; 28.11.2013
comment
Я обновил свой исходный пост, добавив в него записи web.config, связанные с безопасностью, а также стандартные настройки web.config. - person Admir Tuzović; 30.11.2013