如何从claimprincipal中删除现有的索赔

本文关键字:删除 claimprincipal | 更新日期: 2023-09-27 17:51:19

我正在制作一个开发人员工具,用于为内部网站点模拟Roles,以允许开发人员根据需要快速充当任何Role。角色定义为Developer, Team Lead, Team Member, Engineering, Marketing, Guest,通过web页面上的工具调用web Api来添加或删除Claim…好吧,我可以添加,但似乎无法找出.RemoveClaim(claim).TryRemoveClaim(claim)可以访问的地方,以获得此工作。我是否必须创建自定义索赔管理器才能获得此功能,还是我遗漏了什么?

我一直在看System.Security.Claims和几乎所有其他的东西似乎都工作得非常简单,没有提到需要大量的工作来做我需要的。

我使用的是VS 2013/Web Api2和。net 4.5.1。

网站方面只是使用一个简单的ajax调用PUTDELETE功能,直到我得到这个工作的方式,我想要的。在控制器中,我的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,我找不到任何示例代码来删除索赔

如何从claimprincipal中删除现有的索赔

您应该使用标识来添加或删除声明。试着添加一个索赔。

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);

BTW,最好使用User从你的控制器而不是HttpContext.Current.User

另外需要添加的重要内容是确保不要尝试遍历声明集合并删除项。我只是偶然发现了别人写的有bug的代码,一开始我没有发现问题,直到我把它读完。

错误代码为:

        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中的项。项,您将看到关于正在修改集合的零星错误。

这是为我工作的代码,没有得到"声明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);