【问题标题】:Update User Claim not Taking Effect. Why?更新用户声明未生效。为什么?
【发布时间】:2014-03-24 12:10:14
【问题描述】:

我正在使用带有 Owin 和 Claims 身份验证的 ASP.NET MVC 5.1。

用户更改其电子邮件后,我需要更新用户声明,因此我在控制器中尝试:

  ClaimsIdentity identity = (ClaimsIdentity)User.Identity;
  Claim claim = identity.FindFirst(ClaimTypes.Email);
  identity.RemoveClaim(claim);
  identity.AddClaim(new Claim(ClaimTypes.Email, newEmail));

  IOwinContext context = new OwinContext();

  context.Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
  context.Authentication.SignIn(identity);

声明已更改,但是当我刷新页面时,电子邮件声明又是原始的...

cookie 似乎没有更新。知道我做错了什么吗?

是否有可能从身份中获取“IsPersistent”的值,所以当我再次签名时,我将获得相同的值?

谢谢,

米格尔

【问题讨论】:

  • 您找到解决方案了吗?我也有同样的问题。
  • 我找到了对我有用的here 的答案。

标签: asp.net-mvc asp.net-identity


【解决方案1】:

我也遇到了同样的问题,所以只想在这里总结一下我的发现。正如 Chris 所说,答案的基础确实在这里:How to change authentication cookies after changing UserName of current user with asp.net identity 但我发现该线程有点难以理解,而且该问题并不是真正的直接重复。

首先,从当前 OWIN 上下文中获取 AuthenticationManager。一旦你有了它,你可以通过调用AuthenticateAsync 方法获得“isPersistent”的值(以及来自原始SignIn 调用的其他属性)。然后要更新当前用户身份的声明,您只需像这样替换 AuthenticationResponseGrant 属性的值:

var identity = (ClaimsIdentity)User.Identity;

// Call AddClaim, AddClaims or RemoveClaim on the user identity.

IOwinContext context = Request.GetOwinContext();

var authenticationContext = 
    await context.Authentication.AuthenticateAsync(DefaultAuthenticationTypes.ExternalCookie);

if (authenticationContext != null)
{
    authenticationManager.AuthenticationResponseGrant = new AuthenticationResponseGrant(
        identity,
        authenticationContext.Properties);
}

实际更新 cookie 的是 AuthenticationResponseGrant 属性的最终设置。

希望这对其他读者有所帮助。

【讨论】:

  • 如何从 OWIN Context 获取 AuthenticationManager 和 AuthenticationResult?
  • @maxim,参考上面的示例代码,context.Authentication(即Request.GetOwinContext().Authentication)将为您获取当前的AuthenticationManager。之后调用authenticationManager.AuthenticateAsync() 获取AuthenticationResult。
  • +1 表示“实际更新 cookie 的是 AuthenticationResponseGrant 属性的最终设置。”我将IAuthenticationManager 直接注入我的班级,设置AuthenticationResponseGrant 属性,效果很好。谢谢!
  • +1 以获得直接的解释。这让我头疼了好几个小时!谢谢!一点点反馈;在代码的最后,我认为您的意思是使用 authenticationContext.Properties 而不是 authenticationResult.Properties 因为 authenticationResult 在这种情况下不存在。
  • 为我工作,但我不得不将 DefaultAuthenticationTypes.ExternalCookie 更改为 DefaultAuthenticationTypes.ApplicationCookie。谢谢!
【解决方案2】:

抱歉,这是一个 ASP.NET CORE 解决方案 我也对索赔问题提出了质疑,但答案很容易找到。

要刷新 cookie,可以依赖 SignInManager 的 RefreshSignInAsync() 函数;

private readonly UserManager<ApplicationUser> _userManager;
    private readonly ApplicationDbContext _context;
    private readonly SignInManager<ApplicationUser> _signInManager;

    public ApiClubController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, ApplicationDbContext context)
    {
        _userManager = userManager;
        _context = context;
        _signInManager = signInManager;
    }

在你的函数内部:

//GET CURRENT USER
        var usr = await GetCurrentUserAsync();
        //OLD CLAIM
        var myClaims = await _userManager.GetClaimsAsync(usr);
        var oldClaim = myClaims.Where(o => o.Type.Equals("Club")).FirstOrDefault();
        if (oldClaim != null)
        {
            await _userManager.RemoveClaimAsync(usr, oldClaim);
        }

        //CREATE CLUB CLAIM
        var clubClaim = new Claim("Club", "" + id);
        await _userManager.AddClaimAsync(usr, clubClaim);

        //RESET USER COOKIE
        await _signInManager.RefreshSignInAsync(usr);

        //RETURN
        return Ok(company);;

注意: 我在这里使用了一个 API,因为我与 angular 混淆了很多。 如果您使用 API 更新身份,则需要刷新页面才能根据您的声明查看内容

【讨论】:

  • RefreshSignInAsync 方法在哪个程序集中?
  • Microsoft.AspNetCore.Identity
  • 这与await userManager.UpdateSecurityStampAsync(user); 相比如何?我不知道该使用哪一个。
【解决方案3】:

这对我有用。不确定这是否是最好的方法,但更新后的声明在数据库和后续控制器中。

var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
var c = identity.Claims.FirstOrDefault(r => r.Type == "tId");
await UserManager.RemoveClaimAsync(user.Id, c);
await UserManager.AddClaimAsync(user.Id, new Claim("tId", "9032C945-DC5C-4FC9-BE7C-8EDC83A72E58"));

AuthenticationManager.SignOut(DefaultAuthenticationTypes.ExternalCookie);
var identity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
AuthenticationManager.SignIn(new AuthenticationProperties { IsPersistent = isPersistent }, identity);

【讨论】:

  • 这终于对我有用了。我想我被声明列表阻止了。也许它应该使用方法UserManager.GetClaimsAsync 以避免在RemoveClaimAsync 期间出现异常枚举器foreach。 Holp 这将对其他人有所帮助。
  • 这是我获得更新声明的唯一方法。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
相关资源
最近更新 更多