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

前言

從本篇開始將圍繞asp.net core身份驗證寫個小系列,但願你看完本系列後,腦子裏對asp.net core的身份驗證原理有個大體印象。
至於身份驗證是啥?與受權有啥聯繫?就不介紹了,太囉嗦。你若是不曉得,本身去搜搜吧。
個人學習思路是詳細看源碼 > 總結得出一個宏觀上的印象 + 如何使用。
若是發現有啥講錯的望指正,省得誤導觀衆git

咱們偶爾會思考如何設計一個牛X的軟件,其實經過對asp.net core框架自己的學習更划算,一來咱們熟悉了asp.net core框架,再者咱們學習了微軟碰到需求是如何設計的。github

計劃:數據庫

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

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

參考:源碼Artechmvc5基於owin的身份驗證視頻緩存

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

 

身份驗證方式和簡易流程

常見的身份驗證方式:cookie

  • 基於cookie/session的身份驗證原理 - 適合瀏覽器
  • 基於Token身份驗證 - 適合移動端app
  • 集成第三方登陸原理 - 好比集成微信、支付寶登陸

爲了便於理解後續的概念,下面先以最多見的 用戶密碼+cookie的身份驗證方式說說核心流程session

登陸:mvc

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

攜帶cookie請求:app

  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

身份驗證處理器就是用來定義這些步驟的
asp.net core中定義了對應的接口、和抽象類,不一樣的身份驗證方式有不的實現類,好比基於token的身份驗證方式在SignIn時直接加密票證而後返回這個字符串(而不是寫入cookie)
這些步驟都是圍繞身份驗證來定義的,在不一樣地方來調用(好比在登陸頁對於的Action、在請求抵達時、在受權中間件中)

 

身份驗證選項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<方案名,身份驗證方案>

 

身份驗證處理器容器AuthenticationHandlerProvider

能夠暫時把它理解爲Dictionary<方案名, 身份驗證處理器容器>,由於這個對象是每次請求都會建立,而且它提供AuthenticationHandler時時從方案列表中去找到制定方案從而獲得對應的處理器類型而後建立的。若是不理解不要緊,下一篇講流程就懂了

 

身份驗證服務AuthenticationService

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

 

後續

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

相關文章
相關標籤/搜索