Использование настраиваемого RoleProvider с Windows Identity Foundation - STS

Я создал STS, который выполняет часть аутентификации. Он использует поставщика настраиваемого членства. После успешного входа в систему меня перенаправляют на мой сайт RP. В плане аутентификации все работает нормально.

Я определил CustomRolesProvider, определенный в web.config моего веб-сайта RP. Он использует имя пользователя, возвращаемое STS, для извлечения ролей этого пользователя из базы данных RP. Когда я использую Roles.GetRolesForUser, я получаю нужные роли.

У меня есть следующее в web.config моей RP, чтобы только администратор мог предоставлять доступ к папке администратора.

А у поставщика карты сайта securityTrimmingEnabled = "true"

<location path="admin">
    <system.web>
      <authorization>
        <allow roles="admin" />
        <deny users="*" />
      </authorization>
    </system.web>
      </location>

<add name="default" type="System.Web.XmlSiteMapProvider" siteMapFile="Web.sitemap" securityTrimmingEnabled="true" />

Проблема: когда пользователь выполняет роль администратора, вкладки меню для страниц администратора не отображаются. Я действительно проверил, что Roles.IsUserInRole ("admin") возвращает true. Таким образом, роль распознается поставщиком ролей, но не правилами авторизации и поставщиком карты сайта в файле web.config.

Если я закомментирую «местоположение» из web.config, то есть разрешу каждому вошедшему в систему пользователю доступ к папке администратора, мои пункты меню будут отображаться нормально.

Насколько я понимаю WIF, RP может иметь собственную реализацию ролей и не должен полагаться на Roles Claim от STS.

Есть у кого-нибудь идеи?

Обновление 2 (20.01.2012): я обнаружил, что служба STS возвращает заявки на роль, как показано ниже:

http://schemas.microsoft.com/ws/2008/06/identity/claims/role = Manager

Итак, если я изменю <allow roles="admin" /> to <allow roles="Manager" />, роль будет выбрана, и вкладки меню будут отображаться соответствующим образом.

Поэтому я уверен, что мне не хватает ссылки на то, как использовать мои роли, а не ту, которая была возвращена через претензии.

Обновление 2 (20.01.2012): если я добавлю роль в ClaimsIdentity, как показано ниже, она будет работать:

void Application_AuthenticateRequest(object sender, EventArgs e) {
  if (Request.IsAuthenticated) {    
    IClaimsPrincipal claimsPrincipal = HttpContext.Current.User as IClaimsPrincipal;
    IClaimsIdentity claimsIdentity = (IClaimsIdentity)claimsPrincipal.Identity;
    if (!claimsIdentity.Claims.Exists(c => c.ClaimType == ClaimTypes.Role))
    {
      claimsIdentity.Claims.Add(new Claim(ClaimTypes.Role, "admin"));
    }
  }
}

Но тогда как лучше всего добавить этот код? Если я добавляю его в Application_AuthenticateRequest, он добавляется при каждом запросе и продолжает добавлять. (Я исправил это, добавив оператор if)

* Обновление 3 (24.01.2012): * Версия 2 моего кода, который использует мой CustomRoleProvider для получения ролей и затем добавляет его в ClaimsCollection:

void Application_AuthenticateRequest(object sender, EventArgs e) {
 if (Request.IsAuthenticated) {
    string[] roleListArray = Roles.GetRolesForUser(User.Identity.Name);
       IClaimsPrincipal claimsPrincipal = HttpContext.Current.User as IClaimsPrincipal;
       IClaimsIdentity claimsIdentity = (IClaimsIdentity)claimsPrincipal.Identity;
       var roleclaims = claimsIdentity.Claims.FindAll(c => c.ClaimType == ClaimTypes.Role);
       foreach (Claim item in roleclaims)
       {
         claimsIdentity.Claims.Remove(item);
       }

       foreach(string role in roleListArray)
       {
         claimsIdentity.Claims.Add(new Claim(ClaimTypes.Role, role));
       }

       HttpContext.Current.User = claimsPrincipal;
    }

Но я не уверен, что это правильный путь.

Есть кто-нибудь, кто делал что-то подобное ??

Обновление 4 (26.01.2012): обнаружил, что могу использовать Custom ClaimsAuthencationManager (шаг 4), чтобы преобразовать мои утверждения. Я переместил код из метода AuthenticateRequest в Global.asax в метод Authenticate в классе ClaimsAuthenticationManager.

Я сомневаюсь, что может быть лучше, чем это. Я отправлю свое решение в качестве ответа. Но все же, если у кого-то есть другое лучшее решение, не стесняйтесь комментировать.


person gbs    schedule 20.01.2012    source источник


Ответы (2)


Вы можете использовать собственный ClaimsAuthencationManager, однако он будет вызываться при каждом запросе. Я бы рекомендовал использовать WSFederationAuthenticationModule.SecurityToken а>. Используйте свойство ClaimsPrincipal класса SecurityTokenValidatedEventArgs и добавьте роли с помощью своего поставщика. Кроме того, вместо жесткого кодирования типа утверждения роли вы можете рассмотреть возможность использования ClaimsIdentity.RoleClaimType.

Найденные роли будут сохранены в зашифрованном файле cookie (при условии, что вы используете значение по умолчанию).

person Phil Bolduc    schedule 27.01.2012
comment
Проблема в том, что роли добавляются конкретным RP. Другим решением было бы добавить их в вашу настраиваемую STS, но тогда вашей настраиваемой STS потребуется доступ к этой информации. Это было бы лучшим решением, если бы более чем одному RP нужно было знать эту информацию о ролях. - person Kaido; 27.01.2012
comment
В зависимости от ситуации, сведения о ролях, известные STS, могут быть неправильными. Например, если вы используете Google или MSN в качестве STS, должны ли Google и MSN знать о ролях вашей RP? В качестве альтернативы, если вы используете ADFS внутри домена Active Directory, вы можете захотеть, чтобы ADFS предоставляла роль пользователя. Роли могут поступать из групп AD или базы данных aspnet. - person Phil Bolduc; 27.01.2012
comment
@Phil: Спасибо, я посмотрю на событие SecurityTokenValidated и попробую в одном из моих RP. Роли в другом RP обновляются в зависимости от того, какую клиентскую программу выбирает пользователь. Так что в этом случае мне придется проверять их по каждому запросу. - person gbs; 27.01.2012
comment
@Kaido: Я понимаю это, но каждая из моих RP имеет разные реализации ролей, и поэтому переход на STS не сработает для меня. Хотя они используют тот же MembershipProvider для входа в систему, и это то, что у меня есть на STS прямо сейчас. Спасибо. - person gbs; 27.01.2012
comment
ClaimsAuthenticationManager.Authenticate (строка, IClaimsPrincipal) будет вызываться во время обработчика события PostAuthenticateRequest (). - person Phil Bolduc; 27.01.2012
comment
Фил. Я не понял, в каком контексте вы упомянули метод ClaimsAuthenticationManager.Authenticate. В настоящее время я использую его для заполнения моих ролей. - person gbs; 27.01.2012
comment
@gbs Я только пытался сообщить вам, где в жизненном цикле запроса будет вызван метод Authenticate. Скорее всего, для вас это не будет проблемой. - person Phil Bolduc; 29.01.2012

Лучшим решением было бы иметь IdP (текущую STS) и RP-STS (или поставщика федерации). Как вы говорите, если в будущем вы будете полагаться на более чем один IdP (например, вы используете Live или Google и т. Д.), Очень маловероятно, что они предоставят вам необходимые претензии.

Цель RP-STS - как раз нормализовать набор требований к тому, что требуется вашему приложению, не загрязняя ваше приложение проблемами идентификации.

Это выглядело бы так:

введите описание изображения здесь

RP-STS особенно полезен, когда у вас есть:

  1. Многие IdP (ваши и внешние)
  2. Множество приложений
  3. Преобразования утверждений, которые могут применяться ко многим RP. Это RP-STS, являющийся «авторитетом» в отношении знаний о том, что userX играет роль Y. И эти знания не являются исключительными для одного приложения.
  4. Функции перехода протокола

Преобразование (T) будет добавлять / удалять заявки по мере необходимости для каждого приложения, независимо от IdP.

Причина, по которой ваше приложение работает, когда вы добавляете утверждение «роль», но не с Roles.IsUserInRole, заключается в том, что, как правило, приложения проверяют User.IsInRole, который разрешается по набору требований в основном и завершается отключением от поставщика ролей. Возможно, это проблема в том, как разработан поставщик ролей.

Недостатком RP-STS является необходимость управления дополнительным компонентом. Однако сегодня есть и более простые варианты: ACS (Access Control Service) - одна из них. Если вы создаете собственный STS, вы, конечно, можете сделать что угодно.

Правильное место для преобразования утверждений в самом RP - это создание Custom ClaimsAuthenticationManager (уже идентифицированного вами). По крайней мере, это «официальная» точка расширяемости для этого. Хотя другие рецепты тоже могут сработать.

person Eugenio Pace    schedule 31.01.2012
comment
Да, я где-то читал об этом, думаю, в Руководстве по идентификации на основе утверждений. На данный момент у нас нет плана разрешить пользователю входить в систему через каких-либо внешних провайдеров. - person gbs; 01.02.2012
comment
У меня есть ситуация, когда я использую несколько органов власти и настраиваемые утверждения AuthenticationManager. Для преобразования мне нужно определить полномочия, поскольку я не контролирую имя личности, и могут быть дубликаты, если я не использую полномочия. Как мне узнать название органа - person Hemant; 05.08.2013