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()
注销时,两个声明也会被删除,因此下次此用户登录< / strong>,它不再是这些两个声明的成员(我认为两个声明不再存在)
claim2
在请求中保留的事实(即使在向用户添加claim2
时已创建身份验证Cookie )表明声明请不要通过身份验证Cookie 来保持请求,而是通过其他方式。
那么声明如何在请求中保持不变?
修改
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源代码已经可用)?!
谢谢
答案 0 :(得分:11)
好问题。甚至让我做了一个小实验。
这一行:
AuthenticationManager.SignIn(
new AuthenticationProperties { IsPersistent = true }, identity );
不设置Cookie。仅为后面的回调设置Identity
对象。
Cookie仅在控件传递给中间件和一些名为Response.OnSendingHeaders
的OWIN内部方法时设置。
因此,您的代码只是在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 Project的源代码,查看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
对象序列化到数据库中。您通常不会直接访问这些内容,除非您想要去指关节&#34;并在UserManager
之外自己写入该表。
换句话说 - Identity不会设置cookie。 OWIN创建cookie。看看this piece of code:
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和Claim是.Net框架的一部分,可以在OWIN或Identity之外使用。这些不仅用于Asp.Net,还用于Windows应用程序。好的事情.Net现在有开源,您可以浏览所有这些 - 让您更好地了解它们如何一起工作。此外,如果您正在进行单元测试,那么了解内部结构是非常宝贵的,因此您可以在不使用模拟的情况下存根所有功能。
答案 1 :(得分:0)
如果您使用的是AD身份验证和ASP核心2.1或2.2,则当我们配置名为ClaimActions的服务时,会有一个OpenIdConnectOptions选项,借助ClaimActions,您可以编写继承自ClaimActions的类[CustomClaimsFactory],该类实际上也会覆盖其Run方法将设置永久声明,请在下面找到代码:
/* startup.cs */ services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.ClaimActions.Add(new CustomClaimsFactory(
"userName",
"xxxxx@outlook.com"
));
}
/*CustomClaimsFactory run method*/ public override void Run(JObject userData, ClaimsIdentity identity, string issuer)
{
identity.AddClaim(new Claim(_ClaimType, _ValueType, issuer));
}