iT邦幫忙

2021 iThome 鐵人賽

DAY 16
0
自我挑戰組

ASP.NET Core & Blazor系列 第 23

Day 23 ASP.NET Core Identity 說明

  • 分享至 

  • xImage
  •  

前面有說到UserAuthentication()UserAuthorization(),這兩個的差別在於:前者用於驗證登入者是誰,後者則決定登入者可以做什麼。

舉例來說,一個員工要登入員工系統,他必須輸入帳號(如員工 ID、姓名或是 email)、密碼,系統才能知道是誰登入了,這就是 Authentication(驗證),處理 Authentication 的方式有 Cookie、Token、第三方驗證(OAuth 或 API-token)、OpenIdSAML

而當員工登入系統後,一般員工通常不會有跨部門或是管理權限,他只能看到他自己或所屬部門的資訊,例如生產部員工看不到會計部的財務,不過會計部為了計算成本卻看得到生產部的原料價格,這就是 Authorization (授權)。

在決定登入者可以做什麼前,必須先知道登入者是誰,所以UserAuthentication()必須放在UserAuthorization()前面。

ASP.NET Core Identity 使用的是基於 Claim 的驗證,要了解 Claim,必須先了解 Claim、ClaimsIdentity 跟 ClaimsPrincipal 是什麼。

Claim 就是關於使用者的一些資訊,Claim Type 跟 Claim Value(可以不用給)就組成一個 Claim,Claim 可以是姓名、電話、角色、Email甚至是角色等等。Authorization 就是用 Claim 判斷使用者有無授權。
https://ithelp.ithome.com.tw/upload/images/20210923/20140893oWPd9NoPw6.png

ClaimsIdentity 則是多個 Claim 的集合,像是駕照上面記錄了姓名、生日、電話,駕照就是一個 ClaimsIdentity。

ClaimsPrincipal 是多個 ClaimsIdentity 的集合,台灣人都有身分證跟健保卡,有些人還有駕照,身分證、健保卡跟駕照都是 ClaimsIdentity,持有它們的人就是 ClaimsPrincipal。

而每一個 HTTP request 都會產生 HttpContext 物件,該物件就存有目前 request 的資訊,其下可以找到一個型別為 ClaimsPrincipal 的 Property 名為 User,這個 Property 就是由UseAuthentication()引入的 Authentication Middleware 產生的。

登入機制可以用 Cookie 或是 JWT 實作,但 Authentication Middleware 怎麼知道要用哪個方法產生 User Property?那就要看 Authentication Scheme 跟 Authentication Handlers。

Authentication Handlers

Authentication Handlers 就是處理驗證的方式,ASP.NET Core Identity 可以呼叫AuthenticateAsync()API 去驗證使用者已登入,如驗證失敗就呼叫ChallengeAsync()將使用者導回登入頁面,如授權失敗則用ForbidAsync()禁止使用者訪問,當然也可以自己實作這些行為。下面例子中用了 JWT 跟 Cookie 的驗證方式,如果用了前者,就必須驗證 JWT token 並產生 ClaimsPrincipal 回傳到 HttpContext.User 中;使用後者則會檢查當前 request 的 cookie並產生 ClaimsPrincipal。

   services.AddAuthentication()
      .AddJwtBearer()
      .AddCookie();

Authentication Scheme

用了任何一種方式註冊 Authentication Handlers 就稱為 Authentication Scheme,每個 Authentication Scheme 都有一個獨特的名字以識別,且可以自己設定 Authentication Handlers,下面的程式結果跟上面會是一樣,因為它們都有預設的 Scheme Name。

services.AddAuthentication()
    .AddJwtBearer("Bearer")
    .AddCookie("Cookies");

Blazor Authentication

Blazor 用的驗證方式跟 ASP.NET Core 一樣,不過 Blazor WebAssembly 跟 Blazor Server 又有不同,前者的驗證就像任何前端網站一樣可以被繞過,因為使用者端的程式可以被使用者改動,因此發送資料的 API 端一定也需要驗證;後者則可用內建的 AuthenticationStateProvider 取得前面說的 HttpContext.User,筆者此前就是自己繼承並覆寫這項 Service 實作 JWT 驗證的。

AuthenticationStateProvider 就是昨天說到的<AuthorizeView><CascadingAuthenticationState>可以取得當前驗證狀態的原因,但如果沒有要覆寫預設驗證機制的話,建議不要自己在 Component 注入一個 AuthenticationStateProvider 出來,直接使用的缺點很明顯,若當前 request 的驗證狀態有異動,因為你改動了這個 Component 的驗證機制,該 Component 就不會被告知。

可以看到下圖,ApiAuthenticationStateProvider繼承了AuthenticationStateProvider,並覆寫了Task<AuthenticationState>,這個 Property 可以取得當前的驗證狀態,MarkUserAsAuthenticated()MarkUserAsLoggedOut()則是筆者自己寫的方法用以標示使用者通過驗證及登出系統,NotifyAuthenticationStateChanged()顧名思義會通知各個 Component 當前驗證狀態,這就是自己繼承並覆寫的案例。
https://ithelp.ithome.com.tw/upload/images/20210923/201408935iHOVzFcnc.png

下圖則是在 Component 取得當前 request 的 HttpContext.User 及 Claims 的作法,不過這裡是先利用服務取得 User 再取得其下 Claims,其實是多此一舉了。
https://ithelp.ithome.com.tw/upload/images/20210923/20140893qVp2maYa9w.png

如果只是要取得 HttpContext.User,只要如下圖般就可以了,因為 Task<AuthenticationState>會以[CascadingParameter]的方式層層傳遞下去。
https://ithelp.ithome.com.tw/upload/images/20210923/20140893Vye11pVm90.png

Ref:Introduction to Authentication in ASP.NET Core

Ref:ASP.NET Core Blazor authentication and authorization


上一篇
Day 22 ASP.NET Core Identity(2)
下一篇
Day24 <AuthorizeRouteView>運用
系列文
ASP.NET Core & Blazor30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言