主頁 > .NET開發 > asp.net core 3.x 身份驗證-1涉及到的概念

asp.net core 3.x 身份驗證-1涉及到的概念

2020-09-17 10:30:10 .NET開發

前言

從本篇開始將圍繞asp.net core身份驗證寫個小系列,希望你看完本系列后,腦子里對asp.net core的身份驗證原理有個大致印象,
至于身份驗證是啥?與授權有啥聯系?就不介紹了,太啰嗦,你如果不曉得,自己去搜搜吧,
我的學習思路是詳細看原始碼 > 總結得出一個宏觀上的印象 + 如何使用,
如果發現有啥講錯的望指正,免得誤導觀眾

我們偶爾會思考如何設計一個牛X的軟體,其實通過對asp.net core框架本身的學習更劃算,一來我們熟悉了asp.net core框架,再者我們學習了微軟碰到需求是如何設計的,

計劃:

  • 基本介紹 - 概述 + 核心類介紹
  • 基于cookie/session的身份驗證原理 - 適合瀏覽器
  • 基于Token身份驗證 - 適合移動端app
  • 集成第三方登錄原理 - 比如集成微信、支付寶登錄
  • IdentityServer - 目前不鳥解
  • asp.net core Identity - 目前不鳥解

必備知識:asp.net core、配置、選項、依賴注入、中間件等...

參考:原始碼、Artech、mvc5基于owin的身份驗證視頻、ASP.NET Core 運行原理解剖[5]:Authentication

注意:本篇只講涉及到的幾個概念

 

推薦個不錯的流程圖/腦圖工具:https://www.processon.com/i/59accdd8e4b0859febda28e3,點這個鏈接注冊我可以獲得幾個檔案限額,抱拳~

身份驗證方式和簡易流程

常見的身份驗證方式:

  • 基于cookie/session的身份驗證 - 適合瀏覽器
  • 基于JWTToken身份驗證(OAuth2) - 適合移動端app
  • 集成第三方登錄(OAuth2) - 比如集成微信、支付寶登錄

為了便于理解后續的概念,下面先以最簡單常見的 【用戶密碼+cookie】 的身份驗證方式說說核心流程

登錄:

  1. 用戶輸入賬號密碼提交
  2. 服務端驗證賬號密碼
  3. 若驗證成功,則創建一個包含用戶標識的票證(下面會說)
  4. 將票證加密成字串寫入cookie

攜帶cookie請求:

  1. 用戶發起請求
  2. 身份驗證中間件嘗試獲取并解密cookie,進而得到含用戶標識的票證(下面會說)
  3. 將用戶標識設定到HttpContext.User屬性

注意:若身份驗證中間件即使沒有決議得到用戶標識,請求也會繼續執行,此時以匿名用戶的身份在訪問系統

 

用戶標識ClaimsPrincipal

它用來表示當前登錄的用戶,它包含用戶Id + 一些與權限檢查相關的附件屬性(角色、所屬部門)
當請求抵達時“身份驗證中間件”將從請求中決議得到當前用戶,如果獲取成功則賦值給HttpContext.User屬性

所以對于我們來說通常有兩個場景使用它
在任意能訪問HttpContext的地方獲取當前用戶,比如在Controller中,
如果需要自定義實作身份驗證,則我們要想方設法從請求中決議得到用戶,并賦值給HttpContext.User

現在你至少對用戶標識這個概念有點理解了,如果要刨根問底兒就自行搜索關鍵字:asp.net Claims

也許你曾經做過或見過這樣的設計,定義Employee表示當前系統的用戶,當用戶登錄時會從資料庫查詢得到對應的Employee,若賬號密碼驗證通過則將其放入Session或快取中,下次訪問時直接從Session/快取中獲取當前用戶,個人覺得這種設計存在如下問題:

  • 浪費記憶體:我們的業務代碼訪問當前用戶最多的欄位可能只是用戶id,性別、地址、聯系電話、學歷....這些欄位不是每個業務處理都需要的
  • 拋棄了asp.net身份驗證框架:從asp.net 2.0時代微軟就設計了IPrincipal,后續的版本直到mvc5中基于owin的身份驗證都在使用此介面,后續的權限驗證微軟也提供了,也是基于此介面的,但我們放棄了,反而是自己有寫了一套微軟本身就實作的功能,可能多數是覺得自己寫的更簡單,但我覺得判斷哪種方式更合適是在你對兩種方式都了解的情況下再做出判斷,

 

用戶票證AuthenticationTicket

既然有了上面的用戶標識,何不直接在登錄時加密這個標識,決議時直接解密得到呢?因為我們還需要額外的控制,比如過期時間,這個屬性只是在身份驗證階段來判斷是否過期,在我們(如Controller.Action中)使用用戶標識的時候并不需要此欄位,類似的額外欄位根據不同的身份驗證方式可能有很多,因此定義了“用戶票證”這個概念,它包含 用戶標識 + 身份驗證程序中需要的額外屬性(如得到用戶標識的時間、過期時間等)

 

身份驗證處理器AuthenticationHandler

參考上面的用戶名密碼+cookie身份驗證流程我們發現有幾個核心的處理步驟:

  • 在登錄時驗證通過后將用戶標識加密后存盤到cookie,SignIn
  • 當用戶注銷時,需要清楚代表用戶標識的cookie,SignOut
  • 在登錄時從請求中獲取用戶標識,Authenticate
  • 在用戶未登錄訪問受保護的資源時,我們希望跳轉到到登錄頁,Challenge
    • Challenge叫做質詢/挑戰,意思是當發現沒有從當前請求中發現用戶標識是希望怎么辦,可能是跳轉到登錄頁,也可能是直接回應401,或者跳轉到第三方(如QQ、微信)的登錄頁 
  • 因為某種原因(如權限驗證不過),阻止方案,Forbid

身份驗證處理器就是用來跟身份驗證相關的步驟的,這些步驟在系統的不同地方來呼叫(比如在登錄頁對于的Action、在請求抵達時、在授權中間件中),
每個呼叫時都可以指定使用哪種身份驗證方案,如果不提供將使用默認方案來做對應的操作,
不同的身份驗證方式有不同的實作

IAuthenticationHandler介面只定義了最核心的幾個步驟:Authenticate()、Challenge()、Forbid(),登錄和注銷這兩個步驟定義了對應的子介面,當然微軟還為我們定義了抽象類,參考
   

 

某個具體的身份驗證方案的選項AuthenticationSchemeOptions

在上述身份驗證處理的多個步驟中會用到一些選項資料,比如基于cookie的身份驗證 cookeName、有效時長、再比如從請求時從cookie中決議得到用戶標識后回呼選項中的某個回呼函式,允許我們的代碼向除錯中添加額外資料,或者干脆替換整個標識,

所以身份驗證選項用來允許我們控制AuthenticationHandler的執行,不同的身份驗證方式有不同的選項物件,它們直接或間接繼承AuthenticationSchemeOptions

 

身份驗證方案AuthenticationScheme

總結性的說:身份驗證方案 = 名稱 + 身份驗證處理器型別,暫時可以理解一種身份驗證方式 對應 一個身份驗證方案,比如:
基于用戶名密碼+cookie的身份驗證方式 對應的 身份驗證方案為:new AuthenticationScheme("UIDPWDCookie",typeof(CookieAuthenticationHandler))
基于用戶名密碼+token  的身份驗證方式 對應的 身份驗證方案為:new AuthenticationScheme("JwtBearer",typeof(JwtBearerHandler))

身份驗證方案在程式啟動階段配置,啟動后形成一個身份驗證方案串列,
程式運行階段從這個串列中取出指定方案,得到對應的處理器型別,然后創建它,最后呼叫這個處理器做相應處理
比如登錄操作的Action中xxx.SignIn("方案名") > 通過方案名找到方案從而得到對應的處理器型別 > 創建處理器 > 呼叫其SignIn方法

一種特殊的情況可能多種方案使用同一個身份驗證處理器型別,這個后續的集成第三方登錄來說

 

方案、處理器、選項、三者之間的關系

簡單但不準確的理解為:方案名+處理器+選項 = 身份驗證方式

 

身份驗證方案的容器AuthenticationSchemeProvider

身份驗證方案的容器(Dictionary<方案名,身份驗證方案>)
默認是單例形式注冊到依賴注入容器的
在應用啟動時通過AuthenticationOptions添加的各種身份驗證方案會被存盤到這個容器中
各種GetDefaultXXX用來獲取針對特定步驟的默認方案,如:GetDefaultAuthenticateSchemeAsync中間件從請求獲取用戶標識時用來獲取針對此步驟的默認方案、GetDefaultSignInSchemeAsync獲取默認用來登錄的方案、GetDefaultSignOutSchemeAsync...等等,身份驗證的不同步驟可以設定不同的默認方案,如果針對單獨的步驟沒有設定默認方案,則自動嘗試獲取總的默認方案,通過AuthenticationOptions設定這些默認值
身份驗證程序中各個步驟都會通過此物件拿到指定方案,并通過關聯的身份驗證型別獲得最終身份驗證處理器,然后做相應處理

整個應用的身份驗證選項AuthenticationOptions

AuthenticationSchemeBuilder的屬性跟AuthenticationScheme幾乎是一樣對應的,它的Build()方法會生成一個AuthenticationScheme,所以我們可以理解為AuthenticationSchemeBuilder = AuthenticationScheme

上面說的AuthenticationSchemeOptions是指某個具體身份驗證方案的選項,不同身份驗證方案有對應的子類,比如:CookieAuthenticationOptions、JwtBearerOptions.. 它們都是AuthenticationSchemeOptions的子類,AuthenticationOptions則是針對整個身份驗證功能的選項物件,我們需要在應用啟動階段通過它來配置身份驗證功能,可以把它理解為IDictionary<方案名, AuthenticationSchemeBuilder>(方案配置容器) + 一些默認值設定,

在應用啟動階段(Startup.ConfigreService)多次呼叫 AddScheme以添加身份驗證方案,

public void AddScheme(string name, Action<AuthenticationSchemeBuilder> configureBuilder)
{
    var builder = new AuthenticationSchemeBuilder(name);
    configureBuilder(builder);
    _schemes.Add(builder);
}

name方案名;configureBuilder允許我們提供委托對方案進行配置

添加的這些方案最侄訓被存盤到AuthenticationSchemeProvider供其使用

另外DefaultAuthenticateScheme、DefaultSignInScheme、DefaultSignOutScheme..看名字也曉得它是說當我們呼叫某個步驟未指定使用那個方案是的默認選擇

 

身份驗證處理器工廠AuthenticationHandlerProvider

它是以Scope的形式注冊到依賴注入容器的,所以每次請求都會創建一個實體物件,
唯一方法GetHandlerAsync從AuthenticationSchemeProvider獲取指定身份驗證方案,然后通過方案關聯的AuthenticationHandler Type從依賴注入容器中獲取AuthenticationHandler ,獲取的AuthenticationHandler會被快取,這樣同一個請求的后續呼叫直接從快取中拿,
所以也可以把它理解為AuthenticationHandler的運行時容器或工廠
AuthenticationService就是通過它來得到AuthenticationHandler然后完成身份驗證各種功能的

 

身份驗證服務AuthenticationService

身份驗證中的步驟是在多個地方被呼叫的,身份驗證中間件、授權中間件、登錄的Action(如:AccountController.SignIn())、注銷的Action(如:AccountController.SignOut()),身份驗證的核心方法定義在這個類中,但它本質上還是去找到對應的身份驗證處理器并呼叫其同名方法,其實這些方法還進一步以擴展方法的形式定義到HttpContext上了,以SignIn方法為例
HttpContext.SignIn() > AuthenticationService.SignIn() > AuthenticationHandler.SignIn() 

 

后續

這一篇只盡量簡單的說了下身份驗證涉及到的幾個核心概念,如果不明白的可以留言或等到下篇結合理解,下一篇將以用戶名密碼+cookie的身份驗證方式來詳細梳理下流程,

轉載請註明出處,本文鏈接:https://www.uj5u.com/net/64915.html

標籤:.NET Core

上一篇:【原創】在 ASP.NET Core 3.1 中使用 Senparc.Weixin.Work 企業微信 SDK —— 發送文本訊息

下一篇:Docker常用命令

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • WebAPI簡介

    Web體系結構: 有三個核心:資源(resource),URL(統一資源識別符號)和表示 他們的關系是這樣的:一個資源由一個URL進行標識,HTTP客戶端使用URL定位資源,表示是從資源回傳資料,媒體型別是資源回傳的資料格式。 接下來我們說下HTTP. HTTP協議的系統是一種無狀態的方式,使用請求/ ......

    uj5u.com 2020-09-09 22:07:47 more
  • asp.net core 3.1 入口:Program.cs中的Main函式

    本文分析Program.cs 中Main()函式中代碼的運行順序分析asp.net core程式的啟動,重點不是剖析原始碼,而是理清程式開始時執行的順序。到呼叫了哪些實體,哪些法方。asp.net core 3.1 的程式入口在專案Program.cs檔案里,如下。ususing System; us ......

    uj5u.com 2020-09-09 22:07:49 more
  • asp.net網站作為websocket服務端的應用該如何寫

    最近被websocket的一個問題困擾了很久,有一個需求是在web網站中搭建websocket服務。客戶端通過網頁與服務器建立連接,然后服務器根據ip給客戶端網頁發送資訊。 其實,這個需求并不難,只是剛開始對websocket的內容不太了解。上網搜索了一下,有通過asp.net core 實作的、有 ......

    uj5u.com 2020-09-09 22:08:02 more
  • ASP.NET 開源匯入匯出庫Magicodes.IE Docker中使用

    Magicodes.IE在Docker中使用 更新歷史 2019.02.13 【Nuget】版本更新到2.0.2 【匯入】修復單列匯入的Bug,單元測驗“OneColumnImporter_Test”。問題見(https://github.com/dotnetcore/Magicodes.IE/is ......

    uj5u.com 2020-09-09 22:08:05 more
  • 在webform中使用ajax

    如果你用過Asp.net webform, 說明你也算是.NET 開發的老兵了。WEBform應該是2011 2013左右,當時還用visual studio 2005、 visual studio 2008。后來基本都用的是MVC。 如果是新開發的專案,估計沒人會用webform技術。但是有些舊版 ......

    uj5u.com 2020-09-09 22:08:50 more
  • iis添加asp.net網站,訪問提示:由于擴展配置問題而無法提供您請求的

    今天在iis服務器配置asp.net網站,遇到一個問題,記錄一下: 問題:由于擴展配置問題而無法提供您請求的頁面。如果該頁面是腳本,請添加處理程式。如果應下載檔案,請添加 MIME 映射。 WindowServer2012服務器,添加角色安裝完.netframework和iis之后,運行aspx頁面 ......

    uj5u.com 2020-09-09 22:10:00 more
  • WebAPI-處理架構

    帶著問題去思考,大家好! 問題1:HTTP請求和回傳相應的HTTP回應資訊之間發生了什么? 1:首先是最底層,托管層,位于WebAPI和底層HTTP堆疊之間 2:其次是 訊息處理程式管道層,這里比如日志和快取。OWIN的參考是將訊息處理程式管道的一些功能下移到堆疊下端的OWIN中間件了。 3:控制器處理 ......

    uj5u.com 2020-09-09 22:11:13 more
  • 微信門戶開發框架-使用指導說明書

    微信門戶應用管理系統,采用基于 MVC + Bootstrap + Ajax + Enterprise Library的技術路線,界面層采用Boostrap + Metronic組合的前端框架,資料訪問層支持Oracle、SQLServer、MySQL、PostgreSQL等資料庫。框架以MVC5,... ......

    uj5u.com 2020-09-09 22:15:18 more
  • WebAPI-HTTP編程模型

    帶著問題去思考,大家好!它是什么?它包含什么?它能干什么? 訊息 HTTP編程模型的核心就是訊息抽象,表示為:HttPRequestMessage,HttpResponseMessage.用于客戶端和服務端之間交換請求和回應訊息。 HttpMethod類包含了一組靜態屬性: private stat ......

    uj5u.com 2020-09-09 22:15:23 more
  • 部署WebApi隨筆

    一、跨域 NuGet參考Microsoft.AspNet.WebApi.Cors WebApiConfig.cs中配置: // Web API 配置和服務 config.EnableCors(new EnableCorsAttribute("*", "*", "*")); 二、清除默認回傳XML格式 ......

    uj5u.com 2020-09-09 22:15:48 more
最新发布
  • C#多執行緒學習(二) 如何操縱一個執行緒

    <a href="https://www.cnblogs.com/x-zhi/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2943582/20220801082530.png" alt="" /></...

    uj5u.com 2023-04-19 09:17:20 more
  • C#多執行緒學習(二) 如何操縱一個執行緒

    C#多執行緒學習(二) 如何操縱一個執行緒 執行緒學習第一篇:C#多執行緒學習(一) 多執行緒的相關概念 下面我們就動手來創建一個執行緒,使用Thread類創建執行緒時,只需提供執行緒入口即可。(執行緒入口使程式知道該讓這個執行緒干什么事) 在C#中,執行緒入口是通過ThreadStart代理(delegate)來提供的 ......

    uj5u.com 2023-04-19 09:16:49 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    <a href="https://www.cnblogs.com/huangxincheng/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/214741/20200614104537.png" alt="" /&g...

    uj5u.com 2023-04-18 08:39:04 more
  • 記一次 .NET某醫療器械清洗系統 卡死分析

    一:背景 1. 講故事 前段時間協助訓練營里的一位朋友分析了一個程式卡死的問題,回過頭來看這個案例比較經典,這篇稍微整理一下供后來者少踩坑吧。 二:WinDbg 分析 1. 為什么會卡死 因為是表單程式,理所當然就是看主執行緒此時正在做什么? 可以用 ~0s ; k 看一下便知。 0:000> k # ......

    uj5u.com 2023-04-18 08:33:10 more
  • SignalR, No Connection with that ID,IIS

    <a href="https://www.cnblogs.com/smartstar/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/u36196.jpg" alt="" /></a>...

    uj5u.com 2023-03-30 17:21:52 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:15:33 more
  • 一次對pool的誤用導致的.net頻繁gc的診斷分析

    <a href="https://www.cnblogs.com/dotnet-diagnostic/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/3115652/20230225090434.png" alt=""...

    uj5u.com 2023-03-28 10:13:31 more
  • C#遍歷指定檔案夾中所有檔案的3種方法

    <a href="https://www.cnblogs.com/xbhp/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/957602/20230310105611.png" alt="" /></a&...

    uj5u.com 2023-03-27 14:46:55 more
  • C#/VB.NET:如何將PDF轉為PDF/A

    <a href="https://www.cnblogs.com/Carina-baby/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/2859233/20220427162558.png" alt="" />...

    uj5u.com 2023-03-27 14:46:35 more
  • 武裝你的WEBAPI-OData聚合查詢

    <a href="https://www.cnblogs.com/podolski/" target="_blank"><img width="48" height="48" class="pfs" src="https://pic.cnblogs.com/face/616093/20140323000327.png" alt="" /><...

    uj5u.com 2023-03-27 14:46:16 more