ASP.NET Core 使用Cookie驗證身份

来源:http://www.cnblogs.com/tdfblog/archive/2017/08/24/aspnet-core-security-authentication-cookie.html
-Advertisement-
Play Games

ASP.NET Core 1.x提供了通過Cookie "中間件" 將用戶主體序列化為一個加密的Cookie,然後在後續請求中驗證Cookie並重新創建主體,並將其分配給 屬性。如果您要提供自己的登錄界面和用戶資料庫,可以使用作為獨立功能的Cookie中間件。 ASP.NET Core 2.x的一個 ...


ASP.NET Core 1.x提供了通過Cookie 中間件將用戶主體序列化為一個加密的Cookie,然後在後續請求中驗證Cookie並重新創建主體,並將其分配給HttpContext.User屬性。如果您要提供自己的登錄界面和用戶資料庫,可以使用作為獨立功能的Cookie中間件。

ASP.NET Core 2.x的一個主要變化是不再存在Cookie中間件。取而代之的是在Startup.cs文件中的Configure方法中的調用UseAuthentication方法會添加設置HttpContext.User屬性的 AuthenticationMiddleware 中間件。

添加配置

ASP.NET Core 1.x

按下列步驟操作:

  • 在您的項目中安裝Microsoft.AspNetCore.Authentication.CookiesNuGet包。此包包含Cookie中間件。

  • Startup.cs文件中的Configure方法中添加下麵的行,在app.UseMvc()語句之前:

        app.UseCookieAuthentication(new CookieAuthenticationOptions()
        {
            AccessDeniedPath = "/Account/Forbidden/",
            AuthenticationScheme = "MyCookieAuthenticationScheme",
            AutomaticAuthenticate = true,
            AutomaticChallenge = true,
            LoginPath = "/Account/Unauthorized/"
        });

ASP.NET Core 2.x

按下列步驟操作:

  • 如果不使用Microsoft.AspNetCore.All 元包,則在您的項目中安裝2.0版的Microsoft.AspNetCore.Authentication.CookiesNuGet包。

  • Startup.cs文件中的Configure方法中調用UseAuthentication方法:

        app.UseAuthentication();
  • Startup.cs文件中的ConfigureServices方法中調用AddAuthenticationAddCookie方法:

        services.AddAuthentication("MyCookieAuthenticationScheme")
                .AddCookie(options => {
                    options.AccessDeniedPath = "/Account/Forbidden/";
                    options.LoginPath = "/Account/Unauthorized/";
                });

上面的代碼片段配置了以下部分或全部選項:

  • AccessDeniedPath - 當用戶嘗試訪問資源但沒有通過任何授權策略時,這是請求會重定向的相對路徑資源。
  • AuthenticationScheme - 這是一個已知的特定Cookie認證方案的值。當有多個Cookie驗證實例,並且您想限制對一個實例的授權時,這就非常有用。
  • AutomaticAuthenticate - 此標識僅適用於ASP.NET Core 1.x。它表示Cookie身份驗證應在每個請求上運行,並嘗試驗證和重建序列化主體。
  • AutomaticChallenge - 此標識僅適用於ASP.NET Core 1.x。這表示當授權失敗時,1.x Cookie認證應將瀏覽器重定向到LoginPathAccessDeniedPath
  • LoginPath - 當用戶嘗試訪問資源但尚未認證時,這是請求重定向的相對路徑。

其它選項包括為Cookie認證創建的設置選項,身份驗證的Cookie的名稱,Cookie的域和Cookie各種安全屬性。預設情況下,Cookie身份驗證為其創建的任何Cookie使用適當的安全選項,例如:

  • 設置HttpOnly標誌以防止客戶端JavaScript中訪問Cookie
  • 如果請求是通過HTTPS訪問,則將Cookie限製為HTTPS

創建身份認證Cookie

要創建一個保存用戶信息的cookie,您必須構建一個ClaimsPrincipal 保存您希望序列化到Cookie中的信息。

ASP.NET Core 1.x

    await HttpContext.Authentication.SignInAsync("MyCookieAuthenticationScheme", principal);

ASP.NET Core 2.x

    await HttpContext.SignInAsync("MyCookieAuthenticationScheme", principal);

這將創建一個加密的Cookie並將其添加到當前響應中。在調用SignInAsync時,必須在配置中指定的AuthenticationScheme

順便提一下,使用的加密方式是ASP.NET Core的Data Protection系統。如果您在多台機器上進行托管、負載平衡或使用Web集群,則需要配置Data Protection才能使用相同的密鑰和應用程式標識符。

Signing out(登出)

要退出當前用戶並刪除其Cookie,請在控制器中調用以下方法:

ASP.NET Core 1.x

    await HttpContext.Authentication.SignOutAsync("MyCookieAuthenticationScheme");

ASP.NET Core 2.x

    await HttpContext.SignOutAsync("MyCookieAuthenticationScheme");

服務端變化反饋

警告: 一旦創建了認證的Cookie,它將成為唯一的身份來源。即使您在服務系統中禁用用戶,Cookie身份驗證也無法瞭解此信息,只要Cookie有效,用戶仍可登錄。

Cookie認證在其選項中提供了一系列事件。ValidateAsync()事件可用於攔截和重寫Cookie身份驗證。

可以考慮在後端用戶資料庫中增加LastChanged列。為了在資料庫更改時使Cookie無效,您應該首先在創建Cookie時添加一個LastChanged包含當前值的聲明。資料庫更改時,更新LastChanged例的值。

要重寫ValidateAsync()事件的實現,您必須編寫一個具有以下簽名的方法:

    Task ValidateAsync(CookieValidatePrincipalContext context);

ASP.NET Core Identity 在SecurityStampValidator實現了這一邏輯,鏈接地址。示例如下所示:

ASP.NET Core 1.x

    public static class LastChangedValidator
    {
        public static async Task ValidateAsync(CookieValidatePrincipalContext context)
        {
            // Pull database from registered DI services.
            var userRepository = context.HttpContext.RequestServices.GetRequiredService<IUserRepository>();
            var userPrincipal = context.Principal;
    
            // Look for the last changed claim.
            string lastChanged;
            lastChanged = (from c in userPrincipal.Claims
                            where c.Type == "LastUpdated"
                            select c.Value).FirstOrDefault();
    
            if (string.IsNullOrEmpty(lastChanged) ||
                !userRepository.ValidateLastChanged(userPrincipal, lastChanged))
            {
                context.RejectPrincipal();
                await context.HttpContext.Authentication.SignOutAsync("MyCookieAuthenticationScheme");
            }
        }
    }

然後,在Startup.cs文件中的Configure方法中將Cokie認證配置進行重寫:

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        Events = new CookieAuthenticationEvents
        {
            OnValidatePrincipal = LastChangedValidator.ValidateAsync
        }
    });

ASP.NET Core 2.x

    public static class LastChangedValidator
    {
        public static async Task ValidateAsync(CookieValidatePrincipalContext context)
        {
            // Pull database from registered DI services.
            var userRepository = context.HttpContext.RequestServices.GetRequiredService<IUserRepository>();
            var userPrincipal = context.Principal;
    
            // Look for the last changed claim.
            string lastChanged;
            lastChanged = (from c in userPrincipal.Claims
                            where c.Type == "LastUpdated"
                            select c.Value).FirstOrDefault();
    
            if (string.IsNullOrEmpty(lastChanged) ||
                !userRepository.ValidateLastChanged(userPrincipal, lastChanged))
            {
                context.RejectPrincipal();
                await context.HttpContext.SignOutAsync("MyCookieAuthenticationScheme");
            }
        }
    }

然後,將在Startup.csConfigureServices方法中將Cookie服務註冊進行配置:

    services.AddAuthentication("MyCookieAuthenticationScheme")
            .AddCookie(options =>
            {
                options.Events = new CookieAuthenticationEvents
                {
                    OnValidatePrincipal = LastChangedValidator.ValidateAsync
                };
            });

如果要非破壞性地更新用戶主體,可以調用context.ReplacePrincipal(),並將context.ShouldRenew屬性設置為true

Cookie設置選項

CookieAuthenticationOptions類提供了各種配置選項,在創建時調整Cookie的配置。

ASP.NET Core 1.x

  • ClaimsIssuer是由中間件創建的任何聲明時使用的Issuer屬性。
  • CookieDomain是提供Cookie的功能變數名稱。預設情況下,這是發送請求的主機名。瀏覽器僅將Cookie提供給匹配的主機名。您可能希望對此進行調整,以便您的域中的任何主機都可以使用Cookie。例如,將Cookie功能變數名稱設置為.contoso.com,可以使用Cookie的功能變數名稱有contoso.comwww.contoso.comstaging.www.contoso.com等。
  • CookieHttpOnly是一個標識,指定Cookie是否只能由伺服器訪問。預設為true。如果您的應用程式具有Cross-Site Scripting(XSS)的問題,更改此值可能會導致Cookie被盜用。
  • CookiePath可用於隔離在相同主機名上運行的應用程式。如果你有一個應用程式在/app1中運行,並希望限制發送的Cookie只發送到該應用程式,那麼您應該將CookiePath屬性設置為/app1。通過這樣做,Cookie只適用於對/app1或其下任何內容的請求。
  • CookieSecure是一個標識,表示創建的Cookie是否應該被限製為HTTPS,HTTP或HTTPS,或與請求相同的協議。預設為SameAsRequest
  • ExpireTimeSpanTimeSpan類型,在此時間段之後Cookie將過期。將當前日期加上此時間段為創建Cookie的到期日期。
  • SlidingExpiration是一個標識,指示當超過一半的ExpireTimeSpan間隔時,Cookie到期日期是否複位。新的到期日是當前時間加上ExpireTimespan。調用SignInAsync時,可以使用AuthenticationProperties類設置絕對到期時間。絕對到期時間可以通過限制認證Cookie有效的時間來提高應用程式的安全性。

Startup.cs文件中的Configure方法中使用CookieAuthenticationOptions的例子如下:

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        CookieName = "AuthCookie",
        CookieDomain = "contoso.com",
        CookiePath = "/",
        CookieHttpOnly = true,
        CookieSecure = CookieSecurePolicy.Always
    });

ASP.NET Core 2.x

ASP.NET Core 2.x 統一了用於配置Cookie的API。1.x API已被標記為過時,並且在CookieAuthenticationOptions類中引入了一種類型為CookieBuilder新的Cookie屬性。建議您遷移到2.x API。

  • ClaimsIssuer是由Cookie認證創建的任何聲明時使用的Issuer屬性。
  • CookieBuilder.Domain是提供Cookie的功能變數名稱。預設情況下,這是發送請求的主機名。瀏覽器僅將Cookie提供給匹配的主機名。您可能希望對此進行調整,以便您的域中的任何主機都可以使用Cookie。例如,將Cookie功能變數名稱設置為.contoso.com,可以使用Cookie的功能變數名稱有contoso.comwww.contoso.comstaging.www.contoso.com
  • CookieBuilder.HttpOnly是一個標識,指定Cookie是否只能由伺服器訪問。預設為true。如果您的應用程式具有Cross-Site Scripting(XSS)的問題,更改此值可能會導致Cookie被盜用。
  • CookieBuilder.Path可用於隔離在相同主機名上運行的應用程式。如果你有一個應用程式在/app1中運行,並希望限制發送的Cookie只發送到該應用程式,那麼您應該將CookiePath屬性設置為/app1。通過這樣做,Cookie只適用於對/app1或其下任何內容的請求。
  • CookieBuilder.SameSite表示瀏覽器是否允許Cookie被附加到同一站點或跨站點的請求。預設為SameSiteMode.Lax
  • CookieBuilder.SecurePolicy是一個標識,表示創建的Cookie是否應該被限製為HTTPS,HTTP或HTTPS,或與請求相同的協議。預設為SameAsRequest
  • ExpireTimeSpanTimeSpan類型,在此時間段之後Cookie將過期。將當前日期加上此時間段為創建Cookie的到期日期。
  • SlidingExpiration是一個標識,指示當超過一半的ExpireTimeSpan間隔時,Cookie到期日期是否複位。新的到期日是當前時間加上ExpireTimespan。調用SignInAsync時,可以使用AuthenticationProperties類設置絕對到期時間。絕對到期時間可以通過限制認證Cookie有效的時間來提高應用程式的安全性。

Startup.csConfigureServices方法中使用CookieAuthenticationOptions的例子如下:

    services.AddAuthentication()
        .AddCookie(options =>
        {
            options.Cookie.Name = "AuthCookie";
            options.Cookie.Domain = "contoso.com";
            options.Cookie.Path = "/";
            options.Cookie.HttpOnly = true;
            options.Cookie.SameSite = SameSiteMode.Lax;
            options.Cookie.SecurePolicy = CookieSecurePolicy.Always;
        });

持久Cookie和絕對到期時間

您可能希望Cookie在瀏覽器會話中持續存在,並希望設置身份和Cookie傳輸的絕對過期時間。這種持久性應該只能是用戶顯示同意,在登錄時的“記住我”覆選框或類似的機制啟用。您可以通過在創建身份認證Cookie時調用的SignInAsync方法中使用AuthenticationProperties參數來執行這些操作。例如:

ASP.NET Core 1.x

    await HttpContext.Authentication.SignInAsync(
        "MyCookieAuthenticationScheme",
        principal,
        new AuthenticationProperties
        {
            IsPersistent = true
        });

上述代碼片段中使用的AuthenticationProperties類,位於Microsoft.AspNetCore.Http.Authentication命名空間中。

ASP.NET Core 2.x

    await HttpContext.SignInAsync(
        "MyCookieAuthenticationScheme",
        principal,
        new AuthenticationProperties
        {
            IsPersistent = true
        });

上述代碼片段中使用的AuthenticationProperties類,位於Microsoft.AspNetCore.Authentication命名空間中。


上面的代碼段創建一個身份和相應的Cookie,直到瀏覽器關閉。以前通過Cookie設置選項配置的任何滑動過期設置仍然有效。如果Cookie在瀏覽器關閉時過期,瀏覽器會在重新啟動後清除它。如果Cookie在瀏覽器關閉時過期,瀏覽器會在重新啟動後清除它。

ASP.NET Core 1.x

    await HttpContext.Authentication.SignInAsync(
        "MyCookieAuthenticationScheme",
        principal,
        new AuthenticationProperties
        {
            ExpiresUtc = DateTime.UtcNow.AddMinutes(20)
        });

ASP.NET Core 2.x

    await HttpContext.SignInAsync(
        "MyCookieAuthenticationScheme",
        principal,
        new AuthenticationProperties
        {
            ExpiresUtc = DateTime.UtcNow.AddMinutes(20)
        });

上述代碼段創建一個持續20分鐘的身份和相應的cookie。這將忽略以前通過Cookie設置選項配置的任何滑動過期設置。

ExpiresUtcIsPersistent屬性是互斥的。

原文:《Using Cookie Authentication without ASP.NET Core Identity》https://docs.microsoft.com/en-us/aspnet/core/security/authentication/cookie?tabs=aspnetcore2x
翻譯:Sweet Tang
本文地址:<http://www.cnblogs.com/tdfblog/p/aspnet-core-security-authentication-cookie.html >
歡迎轉載,請在明顯位置給出出處及鏈接。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 微信分享代碼,先引入: 獲取簽名: 分享代碼: wxsign輸出的json ...
  • 1、導出Excel : 首先引用NPOI包(Action一定要用FileResult) /// <summary> /// 批量導出需要導出的列表 /// </summary> /// <returns></returns> public FileResult ExportStu2() { //獲取 ...
  • ASP.NET Core 是新一代的 ASP.NET,第一次出現時代號為 ASP.NET vNext,後來命名為ASP.NET 5,隨著它的完善與成熟,最終命名為 ASP.NET Core,表明它不是 ASP.NET 的升級,而是一個重新設計的Web開發框架。而它一個非常重要的變化就是它不再依賴於I ...
  • 基於業務組件模型的工作流模塊設計 摘要 當前基於 BPLE 的業務流程管理(BPM)以及基於 XPDL 的工作流(WF)都有成熟的理論和相應的產品支持,特別是在國內,工作流(WF)的應用十分廣泛。本文從流程入手,結合業務流程管理、工作流、績效管理、個人門戶等概念,將業務流程管理和工作流結合起來 ,搭 ...
  • 通過使用匿名委托(匿名方法),使編程變得更加靈活,有關委托與匿名委托請參考我的前一篇Blog《委托與匿名委托》。 繼續之前示例,代碼如下: 上述程式worker將按照Main給定的參數與計算方式(method),計算出結果返回。根據等效性代碼可以進一步簡化,如下: 看到此處有過js、jquery開發 ...
  • 60年代,在OS中能擁有資源和獨立運行的基本單位是進程,然而隨著電腦技術的發展,進程出現了很多弊端,一是由於進程是資源擁有者,創建、撤消與切換存在較大的時空開銷,因此需要引入輕型進程;二是由於對稱多處理機(SMP)出現,可以滿足多個運行單位,而多個進程並行開銷過大。 因此在80年代,出現了能獨立運 ...
  • 一、文章概述 本演示介紹了WPF的靜態資源和動態資源的基本使用,並對兩者做了簡單的比較。靜態資源(StaticResource)指的是在程式載入記憶體時對資源的一次性使用,之後就不再訪問這個資源了;動態資源(DynamicResource)使用指的是在程式運行過程中然會去訪問資源。 二、定義並使用資源 ...
  • 定義 TemplateBinding是為了某個特定場景優化出來的數據綁定版本--需要把ControlTemplate裡面的某個Property綁定到應用該ControlTemplate的控制項的對應Property上。 用法 區別 1. Binding比TemplateBinding更加靈活強大,但是 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...