坚持要求的索赔
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);
只有在ClaimsIdentity
用户登录时, ClaimsIdentity
和claim2
才会在请求中保留。 换句话说,当用户通过调用SignOut()
注销时 , 两个声明也被删除,因此下次该用户登录时 ,它不再是这两个声明的成员(我假设这两个声明不已经存在了)
claim2
在请求中持久化的事实(即使在将claim2
添加到用户时已经创建了身份validationcookie )这表明声明不会通过身份validationcookie在请求之间claim2
,而是通过其他方式。
那么请求如何在请求中保持不变?
编辑:
1)据我所知, IdentityUserClaim
类型的声明 永远不会保存在cookie中 ?
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
实例不会持久存储在cookie中的原因是因为假设这些声明应该存储在数据库中 ,因此可以在后续请求中从数据库中检索,而声明类型为 Claim
通常不存储在数据库中 ,因此需要将它们保存在cookie中 ?
2)
如果您想深入了解它是如何工作的,请查看Katana项目的源代码
我认为Asp.net Identity 2不是Katana项目的一部分(也就是说,我看到有人问微软什么时候会发布Asp.Net Identity的源代码 ,即使Katana源代码已经可用)?!
谢谢
好问题。 甚至让我做了一个小实验。
这一行:
AuthenticationManager.SignIn( new AuthenticationProperties { IsPersistent = true }, identity );
不设置cookie。 仅为后面的回调设置Identity
对象。
Cookie仅在控件传递给中间件和一些名为Response.OnSendingHeaders
OWIN内部方法时设置。
因此,您的代码只是在identity
对象上添加claim2
,该identity
对象存储在内存中供以后用户使用。 理论上,您甚至可以在完成AuthenticationManager.SignIn
后设置claim1
。 无论如何它将被保留在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
项目。 与Microsoft.Owin.Net45
项目中的AuthenticationManager
一起使用。
更新
要回答您的编辑1 – IdentityUserClaim
确实持久存储到数据库中,这是您可以将持久声明分配给用户的方式。 您可以通过UserManager
将这些添加到用户
await userManager.AddClaimAsync(userId, new Claim("ClaimType", "ClaimValue"));
这将在数据库表中创建表示IdentityUserClaim的记录。 当下次用户登录时,这些声明将从数据库中读取并添加到标识中, ClaimsIdentity.Current
通过属性.Claims
或方法.HasClaim()
在ClaimsIdentity.Current
上.Claims
。
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); }
这里的身份validation管理器是OWIN的一部分。 Identity
是System.Security.Claims
一部分。 所有属于Identity项目的都是CreateIdentityAsync
方法 – 它基本上将用户从数据库转换为所有持久角色和声明的ClaimsIdentity
。
回答你的编辑2 :你是对的,AspNet Identity不是Katana项目的一部分,但Identity使用OWIN(Katana的一部分)进行cookie处理和授权。 身份项目主要处理用户/角色/声明持久性和用户管理,如锁定,用户创建,发送带密码重置的电子邮件,2FA等。
令我感到意外的是, ClaimsPrincipal以及ClaimsIdentity和Claim是.Net框架的一部分,可以在OWIN或Identity之外使用。 这些不仅用于Asp.Net,还用于Windows应用程序。 好的事情.Net现在有开源,您可以浏览所有这些 – 让您更好地了解它们如何一起工作。 此外,如果您正在进行unit testing,那么了解内部结构是非常宝贵的,因此您可以在不使用模拟的情况下存根所有function。