问题 坚持要求的索赔


var user = UserManager.Find(...);

ClaimsIdentity identity = UserManager.CreateIdentity(
          user, DefaultAuthenticationTypes.ApplicationCookie );


var claim1 = new Claim(
          ClaimType = ClaimTypes.Country, ClaimValue = "Arctica", UserId = user.Id );
identity.AddClaim(claim1);

AuthenticationManager.SignIn(
          new AuthenticationProperties { IsPersistent = true }, identity );

var claim2 = new Claim(
          ClaimType = ClaimTypes.Country, ClaimValue = "Antartica", UserId = user.Id );
identity.AddClaim(claim2);

claim1 和 claim2 仅在当时的请求中持久存在 ClaimsIdentity 用户是 登录。换句话说,当用户 退出 通过电话 SignOut()两个索赔 也被删除,因此下次这个用户 登录,它不再是这些的成员 两个索赔 (我假设了 两个索赔 不再存在了)

这个事实 claim2 在请求中持久存在(即使 身份验证cookie 已经创建了 claim2 被添加到用户)建议 索赔 不要通过请求保持持久性 身份验证cookie,但通过其他方式。

怎么样 索赔 坚持要求?

编辑:

1) 据我所知, 索赔类型  IdentityUserClaim 是 决不 坚持在一个 曲奇饼

var user = UserManager.Find(...);

/* claim1 won't get persisted in a cookie */
var claim1 = new IdentityUserClaim
      { ClaimType = ClaimTypes.Country, ClaimValue = "Arctica", UserId = user.Id };
user.Claims.Add(claim1);


ClaimsIdentity identity = UserManager.CreateIdentity(
      user, DefaultAuthenticationTypes.ApplicationCookie );


AuthenticationManager.SignIn(
      new AuthenticationProperties { IsPersistent = true }, identity );

如果我的假设是正确的,那就是原因 IdentityUserClaim 实例不会持久化 曲奇饼 因为它被认为是 这些说法 应存储在 D B 因此可以 后续请求 从一个 D B,而 索赔类型  Claim 通常不存储在 D B 因此,为什么他们需要坚持下去 曲奇饼

2) 

如果您想深入了解一切是如何运作的,请查看   Katana项目的源代码

我想 Asp.net身份2 不是的一部分 Katana项目 (也就是说,我见过有人问微软什么时候会发布 Asp.Net Identity的源代码, 即使 Katana源代码 已经有了)?!

谢谢


11510
2017-08-13 17:06


起源

由于我没有这样做,我不会将其作为答案显示,但我的理解是,声明通常不会保留,而是在内存中添加,就像您在此处显示的那样,在用户登录时添加。至于在代码完成的所有内容完成后,不会在请求结束时为用户创建cookie,包括claim2? - Philip Nelson
如果使用,则声明会保留在Cookie中 UserManager 存储在数据库中(稍后在SignIn上检索)。对于评论的第二部分,您是正确的 - 在请求结束之前不会设置cookie。和 claim1 随着 claim2 坐在内存中,直到在响应上设置标题。 - trailmax


答案:


好问题。甚至让我做了一个小实验。

这一行:

AuthenticationManager.SignIn(
          new AuthenticationProperties { IsPersistent = true }, identity );

不设置cookie。只有套 Identity 对象为后来的回调。

Cookie仅在控件传递给中间件并且调用了一些OWIN内部方法时设置 Response.OnSendingHeaders

所以你的代码只是添加 claim2 在...上 identity 存储在内存中以供后续用户使用的对象。从理论上讲,你甚至可以设定 claim1 你做完之后 AuthenticationManager.SignIn。无论如何它将被保留在cookie中。

如果您尝试在控制器中添加这样的cliam:

    public ActionResult AddNonPersistedClaim()
    {
        var identity = (ClaimsIdentity)ClaimsPrincipal.Current.Identity;
        identity.AddClaim(new Claim("Hello", "World"));

        return RedirectToAction("SomeAction");
    }

此声明不会在Cookie中设置,您将不会在下一个请求中看到它。

如果您想深入了解它是如何工作的,请查看源代码 Katana项目, 旁观 Microsoft.Owin.Security 和 Microsoft.Owin.Security.Cookies 项目。随着 AuthenticationManager 在 Microsoft.Owin.Net45 项目。

更新

回答你的编辑1  - IdentityUserClaim 确实存在于数据库中,这是您可以将持久声明分配给用户的方式。您可以在用户上添加这些内容 UserManager

await userManager.AddClaimAsync(userId, new Claim("ClaimType", "ClaimValue"));

这将在数​​据库表中创建表示IdentityUserClaim的记录。当用户下次登录时,将从数据库中读取这些声明并将其添加到身份中并可用 ClaimsIdentity.Current通过财产 .Claims 或通过方法 .HasClaim()

IdentityUserClaim 什么都不做 - 只是串行化的方式 Claim 对象进入数据库。您通常不会直接访问这些内容,除非您想要“裸露指关节”并自己写入该表 UserManager

换句话说 - Identity不会设置cookie。 OWIN创建cookie。看看吧 这段代码

    public async Task SignInAsync(IAuthenticationManager authenticationManager, ApplicationUser applicationUser, bool isPersistent)
    {
        authenticationManager.SignOut(
            DefaultAuthenticationTypes.ExternalCookie,
            DefaultAuthenticationTypes.ApplicationCookie,
            DefaultAuthenticationTypes.TwoFactorCookie,
            DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie,
            DefaultAuthenticationTypes.ExternalBearer);

        var identity = await this.CreateIdentityAsync(applicationUser, DefaultAuthenticationTypes.ApplicationCookie);
        identity.AddClaim(new Claim(ClaimTypes.Email, applicationUser.Email));

        authenticationManager.SignIn(new AuthenticationProperties() { IsPersistent = isPersistent }, identity);
    }

这里的身份验证管理器是OWIN的一部分。 Identity 是其一部分 System.Security.Claims。所有属于Identity项目的都是 CreateIdentityAsync 方法 - 基本上将用户从数据库转换为 ClaimsIdentity 所有持久的角色和声明。

回答你的编辑2:您是对的,AspNet Identity不是Katana项目的一部分,但Identity使用OWIN(Katana的一部分)进行cookie处理和授权。身份项目主要涉及用户/角色/声明 坚持 和用户管理,如锁定,用户创建,发送密码重置电子邮件,2FA等。

令我感到意外的是 ClaimsPrincipal 随着 ClaimsIdentity 和 要求 是.Net框架的一部分,可以在OWIN或Identity之外使用。这些不仅用于Asp.Net,还用于Windows应用程序。好的事情.Net现在有开源,您可以浏览所有这些 - 让您更好地了解它们如何一起工作。此外,如果您正在进行单元测试,那么了解内部结构是非常宝贵的,因此您可以在不使用模拟的情况下存根所有功能。


9
2017-08-14 15:27



嗨,很好的答案。如果你找到时间,你能看到我做的编辑吗?你确实回答了我原来的问题,所以无论你是否也回答我的后续问题,明天我都会接受你的回答 - bckpwrld
请参阅更新。我已经做了很多身份验证,并找到了一些错综复杂的细节。如果您有兴趣进一步探索,我的实验可用 github.com/trailmax/ClaimsAuthorisation - trailmax
非常感谢你的帮助。会检查你的实验 - bckpwrld
@trailmax所以你在CreateIdentityAsync中所做的一切都是如此。 ClaimsFactory.CreateAsync基本上是持久的请求? - greenhoorn
@greenhoorn声称你穿上了 ClaimsIdentity 在用户登录持久存在于Cookie中之前。如果您在没有登录/注销的情况下对身份进行声明,则这些声明将丢失。 - trailmax