Как удалить существующую претензию из ClaimsPrinciple?
Я делаю инструмент разработчика для подражания Roles
для интранет-сайта, чтобы позволить разработчикам быстро действовать как любой Role
по мере необходимости. Роли определены Developer, Team Lead, Team Member, Engineering, Marketing, Guest
и инструмент на веб-странице вызывает веб-API для добавления или удаления Claim
... ну, я могу добавить, но не могу понять, где .RemoveClaim(claim)
или же .TryRemoveClaim(claim)
можно получить, чтобы получить это работает. Нужно ли создавать собственный менеджер заявок, чтобы получить эту функциональность, или я что-то упустил?
Я смотрю на System.Security.Claims и почти все остальное, кажется, работает очень просто, и нет никаких ссылок на необходимость обширной работы, чтобы сделать то, что мне нужно.
Я использую VS 2013/Web Api2 с.NET 4.5.1.
Сторона сайта просто использует простой вызов ajax PUT
а также DELETE
функциональность, пока я не получу это работать так, как я хочу. Из контроллера мой код cs выглядит так:
public void Put(int id, [FromBody]string role)
{
if (FindClaim(role) != null) return;
var user = HttpContext.Current.User as ClaimsPrincipal;
if (user == null) return;
var claimId = new ClaimsIdentity();
claimId.AddClaim(new Claim(ClaimTypes.Role, role));
user.AddIdentity(claimId);
}
// DELETE api/devroleadjuster/5
public void Delete(int id, [FromBody]string role)
{
var claim = FindClaim(role);
if (claim == null) return;
var user = HttpContext.Current.User as ClaimsPrincipal;
if (user == null) return;
// Why can't I do this????
user.RemoveClaim(claim);
}
private Claim FindClaim(string role)
{
try
{
var user = HttpContext.Current.User as ClaimsPrincipal;
var claim = (from c in user.Claims
where c.Value == role
select c).Single();
return claim;
}
catch (InvalidOperationException)
{
return null;
}
}
Put
работает просто отлично, проблема с Delete
часть моего кода... Я хочу использовать user.RemoveClaim(claim);
код или что-то вроде этого... Я не могу понять, почему я не могу в соответствии с MSDN, и я не могу найти пример кода для удаления претензии.
4 ответа
Вы должны использовать личность, чтобы добавить или удалить претензию. Попробуйте это, чтобы добавить претензию.
var user = User as ClaimsPrincipal;
var identity = user.Identity as ClaimsIdentity;
identity.AddClaim(new Claim(ClaimTypes.Role, "somenewrole"));
Чтобы удалить претензию,
var user = User as ClaimsPrincipal;
var identity = user.Identity as ClaimsIdentity;
var claim = (from c in user.Claims
where c.Value == "somenewrole"
select c).Single();
identity.RemoveClaim(claim);
Кстати, лучше использовать User
от вашего контроллера вместо HttpContext.Current.User
,
Что еще важно добавить, это убедиться, что вы не пытаетесь перебрать коллекцию заявок и удалить элементы. Я просто наткнулся на глючный код, написанный кем-то другим, и сначала я не видел проблемы, пока не прошел ее.
Код ошибки был:
foreach (var claim in identity.Claims)
{
var name = claim.Type;
if (!name.Equals("UserAccountId") && !name.Equals("Email") && !name.Equals("TenantIds"))
{
identity.RemoveClaim(claim);
}
}
В результате претензии были непоследовательно удалены из списка. Простое решение проблемы - перебрать список утверждений, а не сами утверждения, и удалить их следующим образом:
var claimNameList = identity.Claims.Select(x => x.Type).ToList();
foreach (var name in claimNameList)
{
if (!name.Equals("UserAccountId") && !name.Equals("Email") && !name.Equals("TenantIds"))
{
var claim = identity.Claims.FirstOrDefault(x => x.Type == name);
if (claim != null)
identity.RemoveClaim(claim);
}
}
Никогда не стоит перебирать коллекцию, добавлять или удалять элементы. Вы увидите спорадические ошибки и разные результаты в зависимости от ситуации, а в некоторых случаях, например, при переборе элементов в HttpContext.Current.Items, вы увидите спорадические ошибки об изменении коллекции.
Это код, который работал у меня без появления ошибки «заявление X не удалось удалить»:
ClaimsPrincipal currentPrincipal = ClaimsPrincipal.Current;
foreach (var identity in currentPrincipal.Identities)
{
Claim claim = identity.FindFirst(x => x.Value == role);
if (claim != null)
{
identity.RemoveClaim(claim);
}
}
Найдите пользователя, затем удалите его
var user = await _userManager.FindByIdAsync(userId);
var claim = _userManager.GetClaimsAsync(user).Result.FirstOrDefault(c => c.Type == claimType);
var result =await _userManager.RemoveClaimAsync(user, claim);