1. 程式人生 > >ASP.NET Core 中的那些認證中介軟體及一些重要知識點

ASP.NET Core 中的那些認證中介軟體及一些重要知識點

前言

在讀這篇文章之間,建議先看一下我的 ASP.NET Core 之 Identity 入門系列()奠定一下基礎。

有關於 Authentication 的知識太廣,所以本篇介紹幾個在 ASP.NET Core 認證中會使用到的中介軟體,還有Authentication的一些零碎知識點,這些知識點對於 ASP.NET 認證體系的理解至關重要。

在 Github 中 ASP.NET Core 關於 Authentication 的實現有以下幾個包,那麼這幾個包的功能分別是幹什麼用的呢?我們一一看一下。

Microsoft.AspNetCore.Authentication

Authentication 在 ASP.NET Core 中,對於 Authentication(認證) 的抽象實現,此中介軟體用來處理或者提供管道中的 HttpContext 裡面的 AuthenticationManager 相關功能抽象實現。

HttpContext 中的 User 相關資訊同樣在此中介軟體中被初始化。

對於開發人員只需要瞭解此中介軟體中的這幾個物件即可:

  • AuthenticationOptions 物件主要是用來提供認證相關中介軟體配置項,後面的 OpenIdConnect,OAuth,Cookie 等均是繼承於此。
  • AuthenticationHandler 對請求流程中(Pre-Request)中相關認證部分提供的一個抽象處理類,同樣後面的其他幾個中介軟體均是繼承於此。

AuthenticationHandler 中, 有幾個比較重要的方法:

  • HandleAuthenticateAsync :處理認證流程中的一個核心方法,這個方法返回 AuthenticateResult
    來標記是否認證成功以及返回認證過後的票據(AuthenticationTicket)。
  • HandleUnauthorizedAsync:可以重寫此方法用來處理相應401未授權等問題,修改頭,或者跳轉等。
  • HandleSignInAsync:對齊 HttpContext AuthenticationManager 中的 SignInAsync
  • HandleSignOutAsync:對齊 HttpContext AuthenticationManager 中的 SignOutAsync
  • HandleForbiddenAsync:對齊 HttpContext AuthenticationManager 中的 ForbidAsync,用來處理禁用等結果

以上關於 AuthenticationHandler 我列出來的這些方法都是非常容易理解的,我們在繼承Authentication實現我們自己的一箇中間件的時候只需要重寫上面的一個或者多個方法即可。

還有一個 RemoteAuthenticationHandler 它也是繼承AuthenticationHandler,主要是針對於遠端呼叫提供出來的一個抽象,什麼意思呢?因為很多時候我們的認證是基於OAuth的,也就是說使用者的狀態資訊是儲存到Http Header 裡面每次進行往來的,而不是cookie等,所以在這個類裡面了一個HandleRemoteAuthenticateAsync的函式。

Microsoft.AspNetCore.Authentication.Cookies

Cookies 認證是 ASP.NET Core Identity 預設使用的身份認證方式,那麼這個中介軟體主要是幹什麼的呢

我們知道,在 ASP.NET Core 中已經沒有了 Forms 認證,取而代之的是一個叫 “個人使用者賬戶” 的一個東西,如下圖,你在新建一個ASP.ENT Core Web 應用程式的時候就會發現它,它實際上就是 Identity。那麼Forms認證去哪裡了呢?對,就是換了個名字叫 Identity。

在此中介軟體中,主要是針對於Forms認證的一個實現,也就是說它通過Cookie把使用者的個人身份資訊通過加密的票據儲存的Cookie中去,如果看過我之前Identity系列文章的話,那麼應該知道使用者的個人身份資訊就是 ClaimsIdentity 相關的東西。

這個中介軟體引用了Authentication,CookieAuthenticationHandler 類繼承了 AuthenticationHandler 並重寫了 HandleAuthenticateAsync,HandleSignInAsync,HandleSignOutAsyncHandleForbiddenAsync,HandleUnauthorizedAsync 等方法,就是上一節中列出來的幾個方法。

我們主要看一下核心方法 HandleAuthenticateAsync 在 Cookie 中介軟體怎麼實現的:

protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
{
    //讀取並解密從瀏覽器獲取的Cookie
    var result = await EnsureCookieTicket();
    if (!result.Succeeded)
    {
        return result;
    }
     
    // 使用上一步結果構造 CookieValidatePrincipalContext 物件
    // 這個物件是一個包裝類,裡面裝著 ClaimsPrincipal、AuthenticationProperties
    var context = new CookieValidatePrincipalContext(Context, result.Ticket, Options);
    // 預設是空的實現,可以重寫來驗證 CookieValidatePrincipalContext 是否有異常
    await Options.Events.ValidatePrincipal(context);

    if (context.Principal == null)
    {
        return AuthenticateResult.Fail("No principal.");
    }
    // 表示是否需要重新整理Cookie
    if (context.ShouldRenew)
    {
        RequestRefresh(result.Ticket);
    }

    return AuthenticateResult.Success(new AuthenticationTicket(context.Principal, context.Properties, Options.AuthenticationScheme));
}

總結一下就是解密Http請求中的Cookie資訊,然後驗證Cookie是否合法,然後提取Cookie中的資訊返回結果。

還有一個方法就是 HandleSignInAsync ,根據名字可以看出主要是處理登入相關操作的,在這個方法裡面主要是根據Claims資訊生成加入過後的票據,同時會向票據中寫入過期時間,是否持久化等資訊。 是否持久化的意思就是使用者在登陸介面是否勾選了 “記住我” 這個操作。

Microsoft.AspNetCore.Authentication.OAuth

OAuth 是針對於 OAuth 2.0 標準實現的一個客戶端程式,記住是客戶端,它不具備發放Token或者 Client_id ,Code 等的功能,它的作用是幫你簡化對OAuth2.0服務端程式的呼叫。 它對應 OAuth 2.0 標準中的 “獲取Access_Token” 這一步驟,如果對騰訊開放平臺QQ授權比較瞭解的話,就是對應 “使用Authorization_Code獲取Access_Token” 這一步驟。

點選 這裡 檢視圖片詳情。

OAuth 實現的具體細節就不一一介紹了。

Microsoft.AspNetCore.Authentication.OpenIdConnect

獲取 OpenId 是OAuth 授權中的一個步驟,OpenId 它是具體的一個Token Key,不要把他理解成一種授權方式或者和OAuth不同的另外一種東西,他們是一體的。

程式碼上就不詳細說了,和上面的都差不多。主要說一下它們之間的區別或者叫聯絡。

OAuth 它主要是針對於授權(Authorization),而OpenID主要是針對於認證(Authentication),他們之間是互補的。

那什麼叫授權呢? 比如小明是使用我們網站的一個使用者,他現在要在另外一個網站使用在我們網站註冊的賬號,那授權就是代表小明在另外一個網站能夠做什麼東西? 比如能夠檢視資料,頭像,相簿等等,授權會給使用者發放一個叫 Access_Token 的東西。

而認證關注的這個使用者是誰,它是用來證明使用者東西。比如小明要訪問它的相簿,那我們網站就需要小明提供一個叫OpenId的一個東西,我們只認這個OpenId。那小明從哪裡得到它的這個OpenId呢,對,就是使用上一步的Access_Token 來換取這 個 OpenId ,以後訪問的時候不認 Access_Token ,只認識OpenId這個東西。

一般情況下,OpenId 是需要客戶端進行持久化的,那麼對應在 ASP.NET Core Identity 中,就是儲存在 UsersLogin 表裡面的 ProviderKey 欄位,懂了吧,懂了給個推薦唄

Microsoft.AspNetCore.Authentication.JwtBearer

JwtBearer 這個中介軟體是依賴於上一步的 OpenIdConnect 中介軟體的,看到了吧,其實這幾個中介軟體是環環巢狀的。

可能很多同學聽說過 Jwt,但是大多數人都有一個誤區,認為JWT是一種認證方式,經常在QQ群裡面聽過 前面一個同學在問 實際開發中前後端分離的時候安全怎麼做的?,下面一個人回答使用JWT。

其實JWT 它不是一種認證方式,也不是一種認證的技術,它是一個規範,一個標準。

Jwt(Json Web Token)的官網是 https://jwt.io,下面是對JWT的一個說明

JSON Web Tokens are an open, industry standard RFC 7519 method for representing claims securely between two parties.
JSON Web Tokens(JWT) 是一個開放的行業標準( RFC 7519),用於在雙方之間傳遞安全的Claims。

JWT 在身份認證中的應用場景:

在身份認證場景下,一旦使用者完成了登陸,在接下來的每個請求中包含JWT,可以用來驗證使用者身份以及對路由,服務和資源的訪問許可權進行驗證。由於它的開銷非常小,可以輕鬆的在不同域名的系統中傳遞,所有目前在單點登入(SSO)中比較廣泛的使用了該技術。

好了,不過多的說了。 我們還是接著看一下 JwtBearer 中介軟體,同樣它重寫了 HandleAuthenticateAsync 方法。

大致步驟如下:

  1. 讀取 Http Request Header 中的 Authorization 資訊
  2. 讀取 Authorization 值裡面的 Bearer 資訊
  3. 驗證 Bearer 是否合法,會得到一個 ClaimsPrincipal
  4. 使用 ClaimsPrincipal 構建一個 Ticket(票據)
  5. 呼叫 Options.Events.TokenValidated(context),使用者可以重寫此方法驗證Token合法性
  6. 返回驗證成功

其他的知識點

這幾個中介軟體對會有對應的 Options 配置項,在這些配置項中,都會有 AuthenticationScheme, AutomaticAuthenticate, AutomaticChallenge 這幾個屬性,那這幾個東西都是幹嘛的呢?

AuthenticationScheme

我在 《ASP.NET Core 之 Identity 入門(二)》 一文中提到過這個知識點,當時說很重要,這裡可以看到了吧,每一種驗證中介軟體都會使用到這個東西,我比較偏向於把這個翻譯成 “認證方案”。

我們知道,在 MVC 程式中一般通過在 Controller 或者 Action 上 打標記(Attribute)的方式進行授權,最典型的就是新建一個專案的時候裡面的AccountController。

[Authorize]
public class AccountController : Controller
{
}

在 Authorize 這個 Attribute 中,有一個屬性叫做 ActiveAuthenticationSchemes 的東西,那麼這個東西是幹什麼用的呢?

ActiveAuthenticationSchemes 就是對應著中介軟體Options裡面配置的 AuthenticationScheme ,如果你不指定的話,在使用多個身份驗證元件的時候會有問題,會有什麼問題呢?往下看

AutomaticAuthenticate

AutomaticAuthenticate 很簡單,是一個bool型別的欄位,用來配置是否處理 AuthenticationHandler 是否處理請求。或者你可以理解為中介軟體是不是自動的處理認證相關的業務。

AutomaticChallenge

這個重要哦! 當我們使用多個身份驗證中介軟體的時候,那麼就要用到這個配置項了,該配置項是用來設定哪個中介軟體會是身份驗證流程中的預設中介軟體,當代碼執行到 Controller 或者 Action 上的 [Authorize] 這個標記的時候,就會觸發身份驗證流程。預設情況下MVC的Filter會自動的觸發[Authorize],當然也有一種手動觸發Authorize的辦法就是使用HttpContext.Authentication.ChallengeAsync()

實際上,在驗證中介軟體的管道流程中,應該只有一個元件被設定為 AutomaticChallenge = true,但其實大多數的中介軟體這個引數預設都是 true ,這些中介軟體包括(Identity, Cookie, OAuth, OpenId, IISIntegration, WebListener)等, 這就導致了在整個驗證流程中會觸發多箇中間件對其進行相應,這種衝突大部分不是使用者期望的結果。

不幸的是,目前框架對於這種情況並沒有一個健壯的機制,如果開發人員對於這種機制不是很清楚的話,可能會造成很大的困擾。

幸運的是,ASP.NET Core 團隊已經意識到了這個問題,他們將在 NET Standard 2.0 中對此重新進行設計,比如手動觸發的時候應該怎麼處理,有多個的時候怎麼處理,以及會新增一些語法糖。

目前情況下,當有多個驗證中介軟體的時候,應該怎麼處理呢?比如同時使用 Identity 和 JwtBearer。正確的做法是應該禁用掉除 Identity 以外的其他中介軟體的 AutomaticChallenge,然後指定呼叫的AuthenticationScheme。也就是說在Controller或者Action顯式指定 [Authorize(ActiveAuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)] ,或者是可以指定一個策略來簡化授權呼叫 [Authorize("ApiPolicy")]

services.AddAuthorization(options =>
{
    options.AddPolicy("ApiPolicy", policy =>
    {
        policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
        policy.RequireAuthenticatedUser();
    });
});

而預設不帶引數的 [Authorize] 可以指定AuthorizationPolicie:

services.AddAuthorization(options =>
{
    options.DefaultPolicy = new AuthorizationPolicyBuilder("Identity.Application").RequireAuthenticatedUser().Build();
});

注意,手動呼叫 HttpContext.Authentication.ChallengeAsync() 不受 AuthorizationPolicie 影響。

總結

本篇介紹了 ASP.NET Core 有關 Authentication 的幾個中介軟體,然後還有幾個比較重要的知識點,這篇文章內容有點多,對於一些人來說可能需要一點時間消化。

最後,如果你覺得這篇文章對你有幫助的話,謝謝你的【推薦】。

如果你對 .NET Core 感興趣可以關注我,我會定期在部落格分享關於 .NET Core 的學習心得。

相關推薦

ASP.NET Core 那些認證中介軟體一些重要知識點

前言 在讀這篇文章之間,建議先看一下我的 ASP.NET Core 之 Identity 入門系列(一,二,三)奠定一下基礎。 有關於 Authentication 的知識太廣,所以本篇介紹幾個在 ASP.NET Core 認證中會使用到的中介軟體,還有Authentication的一些零碎知識點,這些知識點

ASP.NET Core 基礎知識(二) 中介軟體

中介軟體是一種裝配到應用管道以處理請求和相應的軟體.每個軟體都可以: 1.選擇是否將請求傳遞到管道中的下一個元件; 2.可在呼叫管道中的下一個元件前後執行工作. 管道由 IApplicationBuilder 建立: 每個委託都可以在下一個委託前後執行操作,.此外,委託還可以決定不將請求傳遞給下一

ASP.NET Core如何使用壓縮中介軟體提高Web應用程式效能

> ## 前言 壓縮可以大大的降低我們Web伺服器的響應速度,壓縮從而提高我們網頁的載入速度,以及節省一定的頻寬. > ## 何時使用相應壓縮中介軟體 在IIS,Apache,Nginx中使用基於服務端的響應壓縮技術。中介軟體的執行可能和服務端模組不匹配。HTTP.sys 和Kestrel

ASP.NET Core使用GraphQL - 第二章 中介軟體

前文:ASP.NET Core中使用GraphQL - 第一章 Hello World 中介軟體 如果你熟悉ASP.NET Core的中介軟體,你可能會注意到之前的部落格中我們已經使用了一箇中間件, app.Run(async (context) => { var result =

ASP.NET Core編寫合格的中介軟體

  這篇文章探討了讓不同的請求去使用不同的中介軟體,那麼我們應該如何配置ASP.NET Core中介軟體?其實中介軟體只是在ASP.NET Core中處理Web請求的管道。所有ASP.NET Core應用程式至少需要一箇中間件來響應請求,並且您的應用程式實際上只是中介軟體的集合。當然MVC管道本身就是中介軟體

ASP.NET Core 基於工廠的中介軟體啟用

IMiddlewareFactory/IMiddleware 是中介軟體啟用的擴充套件點。 UseMiddleware 擴充套件方法檢查中介軟體的已註冊型別是否實現 IMiddleware。 如果是,則使用在容器中註冊的 IMiddlewareFactory&

asp.net core使用cookie認證

local 不知道 file version sent space 如何 使用 pub 以admin控制器為要認證的控制器舉例 1.對控制器設置權限特性 //a 認證命名空間 using Microsoft.AspNetCore.Authorization; using

[譯]ASP.NET Core使用MediatR實現命令和中介者模式

在本文中,我將解釋命令模式,以及如何利用基於命令模式的第三方庫來實現它們,以及如何在ASP.NET Core中使用它來解決我們的問題並使程式碼簡潔。因此,我們將通過下面的主題來進行相關的講解。 什麼是命令模式? 命令模式的簡單例項以及中介者模式的簡單描述 MVC中的瘦控制器是什麼?我們是如如何實現使控制器

ASP.NET Core jwt授權認證的流程原理

[TOC] ## 1,快速實現授權驗證 什麼是 JWT ?為什麼要用 JWT ?JWT 的組成? 這些百度可以直接找到,這裡不再贅述。 實際上,只需要知道 JWT 認證模式是使用一段 Token 作為認證依據的手段。 我們看一下 Postman 設定 Token 的位置。 ![](https://

Asp.Net CoreJson序列化處理整理

忽略 化工 res ref 工具 使用 asp.net ctr ide 一、Asp.Net Core中的Json序列化處理使用的是Newtonsoft.Json,更多參考:C# Newtonsoft.Json JsonSerializerSettings配置序列化操作,C#

asp.net core負載均衡場景下http重定向https的問題

進行 urn 循環 == 是否 美的 err add ddr 上周欣喜地發現,微軟官方終於針對 asp.net core 在使用負載均衡的情況下從 http 強制重定向至 https 的問題提供了解決方法。 app.UseForwardedHeaders(new Fo

體驗 ASP.NET Core 的多語言支持(Localization)

lan expander -c blank 根據 body esp doc input 首先在 Startup 的 ConfigureServices 中添加 AddLocalization 與 AddViewLocalization 以及配置 RequestLocaliz

ASP.NET Core 使用Cookie中間件

新用戶 private 應該 validate ive mes esp tom 全選 http://ASP.NET Core 提供了Cookie中間件來序列化用戶主題到一個加密的Cookie中並且在後來的請求中校驗這個Cookie,再現用戶並且分配到HttpContext對

ASP.NET.Core使用AutoMapper

nvi 創建 reat fin intern stat 中間件 isa addm 首先需要在NuGet中引用AutoMapper的類庫 install-package AutoMapper install-package AutoMapper.Extens

IdentityServer4在Asp.Net Core的應用(一)

types eid 應用 temp ant 所有 com 好用 nts IdentityServer4是一套身份授權以及訪問控制的解決方案,專註於幫助使用.Net 技術的公司為現代應用程序建立標識和訪問控制解決方案,包括單點登錄、身份管理、授權和API安全。

IdentityServer4在Asp.Net Core的應用(二)

str discover content 用戶信息 完成 服務 resp csharp line 繼續上次授權的內容,客戶端模式後我們再說以下密碼模式,先回顧下密碼模式的流程: 我們還是使用上次的代碼,在那基礎上修改,在IdentityServer4裏面有一個Id

asp.net core遇到需要自定義數據包解密方法的時候

聲明 AD AR 但是 sof AC asp 參數聲明 request 最近將公司的項目用.netcore重寫, 服務的http外部接口部分收發消息是DES加解密的, 那麽在asp.net core mvc的action處理之前需要加入解密這個步驟. 我第一想到的是用f

ASP.NET Core使用Razor視圖引擎渲染視圖為字符串(轉)

http onf ces mod ado efault his .html 返回 一、視圖渲染說明 在有些項目需求上或許需要根據模板生產靜態頁面,那麽你一樣可以用Razor語法去直接解析你的頁面從而把解析的頁面生成靜態頁,這樣的使用場景很多,不限於生成靜態頁面,視圖引擎為我

asp.net coreIHttpContextAccessor和HttpContextAccessor的妙用

class sys image 只需要 iap href build .com bubuko 分享一篇文章,關於asp.net core中httpcontext的拓展。 現在,試圖圍繞HttpContext.Current構建你的代碼真的不是一個好主意,但是我想如果你

Asp.Net Core利用Seq組件展示結構化日誌功能

eve 發布 哪裏 HA 快速 inf ron void 級別 在一次.Net Core小項目的開發中,掌握的不夠深入,對日誌記錄並沒有好好利用,以至於一出現異常問題,都得跑動服務器上查看,那時一度懷疑自己肯定沒學好,不然這一塊日誌不可能需要自己扒服務器日誌來查看,果然,很