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

Gre*_*son 24 c# claims-based-identity wif asp.net-web-api

我正在制作一个开发人员工具来模仿RolesIntranet站点,以便开发人员能够Role根据需要快速执行任何操作.定义的角色Developer, Team Lead, Team Member, Engineering, Marketing, Guest,并在网页上的工具向Web API的调用来添加或删除的Claim...好,我可以添加,但似乎无法找出的.RemoveClaim(claim).TryRemoveClaim(claim)可以访问得到这个工作.我是否必须创建自定义声明管理器才能获得此功能,或者我是否遗漏了某些内容?

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

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

网站方面只是使用简单的ajax调用PUTDELETE功能,直到我按照我想要的方式工作.从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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

Put作品就好了,问题是用Delete的我的代码部分......我想使用的user.RemoveClaim(claim);代码或类似的东西.我不明白为什么我不能根据MSDN,我无法找到删除声明的任何示例代码.

Bad*_*dri 34

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

var user = User as ClaimsPrincipal;
var identity = user.Identity as ClaimsIdentity;
identity.AddClaim(new Claim(ClaimTypes.Role, "somenewrole"));
Run Code Online (Sandbox Code Playgroud)

要删除声明,

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);
Run Code Online (Sandbox Code Playgroud)

顺便说一句,最好User从你的控制器而不是使用HttpContext.Current.User.

  • @Badri.你知道如何在页面加载之间保持这种状态吗?我一直恢复到改变之前的状态. (3认同)
  • `HttpContext`紧紧地联系你到网络托管.最好使用"User"属性形式的抽象.查看此链接 - http://aspnetwebstack.codeplex.com/workitem/1294,特别是David Matson的回复(搜索davidmatson写于2013年9月13日下午9:18). (2认同)
  • 尝试使用Identity删除声明时出错:"声明'time_zone_string:Mountain Standard Time'无法删除.它不是本身份的一部分,也不是包含此身份的委托人拥有的声明.例如,在创建具有角色的GenericPrincipal时,Principal将拥有该声明.角色将通过构造函数中传递的Identity公开,但不会由Identity实际拥有.RolePrincipal存在类似的逻辑 (2认同)

小智 5

需要添加的其他重要内容是确保您不要尝试遍历索赔集合并删除项目。我只是偶然发现了别人编写的错误代码,起初直到逐步解决之前,我才发现问题。

越野车代码是:

        foreach (var claim in identity.Claims)
        {
            var name = claim.Type;
            if (!name.Equals("UserAccountId") && !name.Equals("Email") && !name.Equals("TenantIds"))
            {
                identity.RemoveClaim(claim);
            }
        }
Run Code Online (Sandbox Code Playgroud)

结果是不一致地从列表中删除了索赔。解决此问题的简单方法是遍历声明列表,而不是声明本身,然后以这种方式删除它们:

        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);
            }
        }
Run Code Online (Sandbox Code Playgroud)

遍历集合并添加或删除项目绝不是一个好主意。根据情况,您将看到偶发的错误和不同的结果,在某些情况下,例如遍历HttpContext.Current.Items中的项目,您将看到有关修改集合的偶发错误。