[英]Persisting claims across requests
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
跨請求持久化的事實(即使在將claim2
添加到 user 時已經創建了身份驗證 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 中的原因,因為假設這些聲明應該存儲在DB 中,因此可以在后續請求中從DB檢索,而Claim
類型的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
。 理論上,您甚至可以在完成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 Project的源代碼,查看Microsoft.Owin.Security
和Microsoft.Owin.Security.Cookies
項目。 與Microsoft.Owin.Net45
項目中的AuthenticationManager
一起使用。
更新
回答您的編輯 1 - IdentityUserClaim
確實持久保存到數據庫中,這是您可以將持久聲明分配給用戶的方式。 您通過UserManager
在用戶上添加這些
await userManager.AddClaimAsync(userId, new Claim("ClaimType", "ClaimValue"));
這會在您的數據庫表中創建表示 IdentityUserClaim 的記錄。 當用戶下次登錄時,這些聲明會從數據庫中讀取並添加到身份中,並通過屬性.Claims
或方法.HasClaim()
在ClaimsIdentity.Current
上可用。
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和Claim是 .Net 框架的一部分,可在 OWIN 或 Identity 之外使用。 這些不僅在 Asp.Net 中使用,而且在 Windows 應用程序中使用。 好在 .Net 現在是開源的,您可以瀏覽所有這些 - 讓您更好地了解它們是如何協同工作的。 此外,如果您正在進行單元測試,了解內部結構是非常寶貴的,因此您可以在不使用模擬的情況下對所有功能進行存根。
如果您使用的是 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));
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.