簡體   English   中英

使用 ASP.NET Core 2.1 / 3+ 身份驗證身份驗證 cookie

[英]Validate authentication cookie with ASP.NET Core 2.1 / 3+ Identity

在 ASP.NET Core 2(有或沒有Identity )中使用 Cookie 身份驗證時,可能會發生用戶的電子郵件或名稱更改,甚至帳戶在 cookie 的生命周期內被刪除的情況。 這就是文檔指出應該驗證 cookie 的原因。 文檔中的示例注釋為

此處描述的方法在每個請求上都會觸發。 這可能會導致應用程序性能下降。

所以我想知道驗證 cookie principal 的最佳模式什么 我在Startup.cs所做的是訂閱OnValidatePrincipal事件並檢查主體的有效性,例如每 5 分鍾通過將LastValidatedOn聲明附加到 cookie,如下所示:

services.ConfigureApplicationCookie(options =>
{
    // other cookie options go here

    options.Events.OnValidatePrincipal = async context =>
    {
        const string claimType = "LastValidatedOn";
        const int reValidateAfterMinutes = 5;

        if (!(context.Principal?.Identity is ClaimsIdentity claimIdentity)) return;

        if (!context.Principal.HasClaim(c => c.Type == claimType) ||
            DateTimeOffset.Now.UtcDateTime.Subtract(new DateTime(long.Parse(context.Principal.Claims.First(c => c.Type == claimType).Value))) > TimeSpan.FromMinutes(reValidateAfterMinutes))
        {
            var mgr = context.HttpContext.RequestServices.GetRequiredService<SignInManager<ApplicationUser>>();
            var user = await mgr.UserManager.FindByNameAsync(claimIdentity.Name);
            if (user != null && claimIdentity.Claims.FirstOrDefault(c => c.Type == "AspNet.Identity.SecurityStamp")?.Value == await mgr.UserManager.GetSecurityStampAsync(user))
            {
                claimIdentity.FindAll(claimType).ToList().ForEach(c => claimIdentity.TryRemoveClaim(c));
                claimIdentity.AddClaim(new Claim(claimType, DateTimeOffset.Now.UtcDateTime.Ticks.ToString(), typeof(long).ToString()));
                context.ShouldRenew = true;
            }
            else
            {
                context.RejectPrincipal();
                await mgr.SignOutAsync();
            }
        }
    };
});

@MarkG 為我指明了正確的方向,謝謝。 在仔細查看SecurityStampValidatorIdentity 的源代碼后,我就明白了。 實際上,我隨問題發布的示例代碼是不必要的,因為 ASP.NET Core Identity 以更好的方式提供了開箱即用的功能。

由於我還沒有找到這樣的摘要,也許它對其他人也有幫助。

什么與身份驗證 cookie 驗證無關

......但還是很高興知道......

services.ConfigureApplicationCookie(options =>
{
    options.Cookie.Expiration = TimeSpan.FromDays(30);
    options.ExpireTimeSpan = TimeSpan.FromDays(30);
    options.SlidingExpiration = true;
});

過期時間跨度

默認為TimeSpan.FromDays(14)

身份驗證票的簽發時間是 cookie ( CookieValidatePrincipalContext.Properties.IssuedUtc ) 的一部分。 當 cookie 被發送回服務器時,當前時間減去發布時間必須大於ExpireTimeSpan 如果不是,用戶將被注銷而無需進一步調查。 在實踐中,設置ExpireTimeSpan主要與設置為true SlidingExpiration一起使用。 這是確保用戶積極使用應用程序的一種方式,例如不會讓設備無人看管。 TimeSpan s 將立即注銷用戶(但不是TimeSpan.Zero )。

需要什么來控制身份驗證 cookie 驗證

services.AddOptions();
services.Configure<SecurityStampValidatorOptions>(options =>
{
    // This is the key to control how often validation takes place
    options.ValidationInterval = TimeSpan.FromMinutes(5);
});

驗證間隔

默認為TimeSpan.FromMinutes(30)

這決定了驗證 cookie 的有效性將根據持久存儲進行檢查的時間跨度。 它是通過為服務器的每個請求調用SecurityStampValidator來完成的。 如果當前時間減去 cookie 的發布時間小於或等於ValidationInterval ,則將調用ValidateSecurityStampAsync 這意味着ValidationInterval = TimeSpan.Zero導致為每個請求調用ValidateSecurityStampAsync

注意UserManager必須支持獲取安全標記,否則會失敗。 對於自定義用戶管理器或用戶存儲,兩者都必須正確實現IUserSecurityStampStore<TUser>

Startup中加載服務的順序

需要注意的是: services. AddIdentity() services. AddIdentity()還為身份驗證 cookie 設置默認值。 如果在services.ConfigureApplicationCookie()之后添加它,這將覆蓋之前的設置。 我在上面的前面調用了services.Configure<SecurityStampValidatorOptions>()

再次感謝@MarkG 為我們指明了方向。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM