更新后的Claim值未反映在后续请求中

时间:2019-04-02 07:16:44

标签: c# asp.net-web-api

在我的项目中,我使用的是基于令牌的身份验证,成功登录后,我将一些特定于用户的值存储在用户的令牌中,并为此使用了Claims。

下面是我用于在登录后存储声明的代码:

User user = new UserManager().GetUser(UserName, Password);

var claims = new List<Claim>()
{
   new Claim(ClaimTypes.Name, user.FullName),
   new Claim(ClaimTypes.Email, user.Email),
   new Claim("IsLocked", Convert.ToString(user.IsLocked))
};

AuthenticationProperties properties = CreateProperties(context.UserName);
ClaimsIdentity oAuthIdentity = new ClaimsIdentity(claims, Startup.OAuthOptions.AuthenticationType);
var ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);

如您在上面的代码中看到的那样,我声称可以存储用户的 IsLocked 值。根据要求,我需要阻止帐户被锁定的用户访问每个API操作。为此,我创建了一个自定义操作过滤器,并在其中使用了 IsLocked 声明的值,因此,如果用户的声明值表明该用户帐户已锁定,则阻止执行操作。

以下是我的自定义操作过滤器的代码:

public class AllowActiveUsersAttribute : ActionFilterAttribute
{
    public AllowActiveUsersAttribute()
    {

    }

    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        var identity = (ClaimsPrincipal)Thread.CurrentPrincipal;

        if (Convert.ToBoolean(identity.Claims.Where(c => c.Type == "IsLocked").Select(c => c.Value).SingleOrDefault()))
        {
            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
        }
    }
}

然后在所有Web API操作上使用此自定义属性,例如:

[AllowActiveUsers]
public async Task<IHttpActionResult> GetAccountDetails()

此代码可以正常工作,并且当我使用锁定的帐户登录并尝试使用任何API端点时,出现“未授权”错误。

在我们的系统中,我们有一些规则,违反这些规则可以锁定用户的帐户。帐户锁定后,用户将无法访问任何API端点。因此,成功登录后(使用未锁定的帐户),如果用户违反任何规则,则他/她的帐户应立即被锁定,此后,他/她一定不能使用任何API端点。

为此,我添加了代码以更新 IsLocked 声明的值,并成功更新了声明值。但是,当我尝试在自定义操作中获取 IsLocked 声明的值时,我得到的是相同的旧值,而不是新的返回值。下面是我用来更新声明值的代码。

// check for the existing claim and remove it
var user = User as ClaimsPrincipal;
var identity = user.Identity as ClaimsIdentity;
var claim = (from c in user.Claims where c.Type == "IsLocked" select c).FirstOrDefault();
if (claim != null)
    identity.RemoveClaim(claim);

// add new claim
identity.AddClaim(new Claim("IsLocked", Convert.ToString(true)));
var authenticationManager = HttpContext.Current.GetOwinContext().Authentication;
authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(new ClaimsPrincipal(identity), new AuthenticationProperties() { IsPersistent = true });

您能否建议我如何在custom属性中获取新值,以便如果用户的帐户被锁定,然后从下一个请求开始,则不应该受理任何API请求?

1 个答案:

答案 0 :(得分:0)

这是因为您仍在使用旧的/现有的令牌,而这些令牌仍然没有更新的值IsLocked,因此没有方案。为了解决这个问题,用户要么必须通过生成具有更新值的新令牌来重新开始。本质上,必须生成一个新的访问令牌。

请参阅此问题链接以进一步了解https://github.com/IdentityServer/IdentityServer3/issues/2783