Использование пользовательского RoleProvider с Windows Identity Foundation - STS - PullRequest
3 голосов
/ 20 января 2012

Я создал 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 может иметь собственную реализацию ролей и не должен полагаться на утверждение ролей из 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): Если я добавлю роль к заявке, как показано ниже, она будет работать:

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)

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

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;
    }

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

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

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

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

Ответы [ 2 ]

3 голосов
/ 01 февраля 2012

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

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

Это будет выглядеть следующим образом:

enter image description here

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

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

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

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

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

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

3 голосов
/ 27 января 2012

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

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

...