Я создал 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.
Я сомневаюсь, что может быть лучше, чем это. Я отправлю свое решение в качестве ответа. Но все же, если у кого-то есть другое лучшее решение, не стесняйтесь комментировать.