2012-01-20 4 views
3

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

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

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

И провайдер карты сайта имеет securityTrimmingEnabled = «истинный»

<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" /> 

Проблема: Когда пользователь находится в роли администратора, вкладки меню для администратора страниц не showup. Я проверил, что Roles.IsUserInRole («admin») возвращает true. Таким образом, роль распознается поставщиком ролей, но не правилами авторизации и поставщиком Sitemap в web.config.

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

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

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

Обновление 2 (01/20/2012): я обнаружил, что СТС возвращает роль утверждает, как показано ниже:

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

Так что если я изменить <allow roles="admin" /> to <allow roles="Manager" /> роль подобран и вкладки меню показаны соответственно ,

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

Update 2 (01/20/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, он добавляется по каждому запросу и продолжает добавлять. (я это исправил, добавив, если заявление)

* Update 3 (01/24/2012): * Version 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 (01/26/2012): Обнаружено, что я могу использовать Custom ClaimsAuthencationManager (Шаг 4), чтобы преобразовать свои претензии. Я переместил код в методе AuthenticateRequest в метод Global.asax для проверки подлинности в классе ClaimsAuthenticationManager.

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

ответ

3

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

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

+0

Проблема в том, что роли добавляются конкретным RP.Другим решением было бы добавить их в пользовательскую STS, но тогда ваш пользовательский STS должен был бы получить доступ к этой информации. Это было бы лучшим решением, если бы более одной RP необходимо было знать эту информацию о роли. – Kaido

+0

В зависимости от ситуации наличие ролей, известных STS, может быть неправильным. Например, если вы используете Google или MSN в качестве STS, должны ли Google и MSN знать о ролях вашего RP? Кроме того, если вы используете ADFS внутри домена Active Directory, вам может потребоваться предоставить ADFS роль пользователя. Роли могут поступать от групп AD или базы данных aspnet. –

+0

@Phil: Спасибо, я посмотрю на событие SecurityTokenValidated и попробую в одном из моих RP. Роли в другом RP обновляются на основе того, какой пользователь клиент-программа выбирает. Поэтому в этом случае мне придется проверять их по каждому запросу. – gbs

3

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

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

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

enter image description here

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

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

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

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

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

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

+0

Да, я читал об этом где-то, я думаю, в Руководстве по идентификации на основе претензий. Пока у нас нет плана, позволяющего пользователю войти в систему через внешних поставщиков. – gbs

+0

У меня есть ситуация, когда я использую несколько полномочий и пользовательских требованийAuthenticationManager. Для трансформации мне нужно выяснить полномочия, поскольку у меня нет контроля над идентификационным именем, и могут быть дубликаты, если я не использую полномочия. Как получить имя органа – Hemant