如何从ClaimsPrinciple中删除现有声明?

我正在制作一个开发人员工具,用于模拟Intranet站点的Roles ,以允许开发人员根据需要快速充当任何Role 。 定义的角色是Developer, Team Lead, Team Member, Engineering, Marketing, Guest和网页上的工具调用Web Api来添加或删除Claim …我可以添加但似乎无法找到可以访问.RemoveClaim(claim).TryRemoveClaim(claim)以获得此function。 我是否必须创建自定义声明管理器才能获得此function,或者我是否遗漏了某些内容?

我一直在关注System.Security.Claims ,几乎所有其他东西似乎都非常简单,并且没有任何参考需要大量工作来完成我需要的工作。

我在.NET 4.5.1中使用VS 2013 / Web Api2。

网站方面只是使用简单的ajax调用PUTDELETEfunction,直到我按照我想要的方式工作。 从Controller,我的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,我找不到任何删除索赔的示例代码。

您应该使用标识来添加或删除声明。 试试这个来添加声明。

 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中的项目,您将看到有关正在修改的集合的偶发错误。