想像我們接手管理一棟大樓,我們都知道大樓裡有很多項工作,例如驗證訪客身份、收包裹或澆花,因為我們很懶我們決定請一個管理員來幫我們處理這些事。

這個管理員很敬業,我們可以指定他要做什麼工作,而且他都會依照需求、規格及流程執行。

當我們跟這個管理員說我們需要他在人員進入大樓時驗證訪客的身份,這個要求就相當於我們把 authentication middleware 加入到程式中。管理員現在看到訪客要進入大樓時就會去驗證這個訪客的身份,就相當於執行 authentication service。

當然,我們需要告訴管理員有哪些驗證的方法,不然他不會曉得有哪些驗證方法可以用,例如可以用大樓發放的磁卡或是用通關密語驗證使用者。只要告訴管理員有哪些方法可以驗證訪客的身份他就會知道在哪種情況下有哪些 SOP 可以用來驗證訪客身份。

給管理員的驗證方法就相當於 authentication scheme,例如「用大樓發放的磁卡」驗證,這種方法就是一個 scheme。而實際驗證時遇到哪種情況該如何處理,就會定義在一個驗證的指南並交給管理員,這個指南就是 authentication handler。

設定驗證機制

在 ASP.NET Core 中,驗證由 authentication middleware 負責處理,authentication middleware 使用 authentication service 執行驗證。

在程式中時常會有驗證請求的需求,而驗證請求又有許多種不同的方法或方案,在 ASP.NET Core 中我們將驗證方案稱呼為 authentication scheme。一個程式中可以有很多種不同的 authentication scheme,例如使用 cookie 驗證的 scheme、使用 JWTBearer 驗證的 Scheme或是自訂驗證方式的 Scheme。當我們決定選用某種 scheme 時,需將該 scheme 註冊到 authentication service(在 Program.cs 中使用AddAuthentication()及需要的 scheme)。

Authentication scheme 包含了 authentication handler 和其他相關設定(例如由外部傳入要用於 handler 的設定值)。authentication handler 負責驗證使用者是否合法,並且需定義當使用者合法或不合法時該如何處理。

要使用 authentication middleware 除了要設定 authentication service 以外,還需要將 UseAuthentication 註冊到程式中,UseAuthentication 必須放在任何需要驗證才能使用的 middleware 之前才能有效保護資源。

當只有一個 scheme 被註冊,該 scheme 會自動變成 default scheme。如果有多個 scheme 被註冊但是沒有指定 default scheme,則需要在每個 authorize attribute 或任何需要用到 scheme 的地方明確指定要使用的 scheme,否則會拋出 InvalidOperationException 錯誤。

執行驗證

在需要驗證的地方使用 authorization attributes 指定一個或多個 scheme。

Authentication Scheme

Authentication Scheme 是一個包含 authentication handler 和 authentication scheme option 的驗證方案。每個方案內會描述 authentication、challenge 及 forbid 等行為。

每個 authentication Scheme 都有一個名稱,當要使用 authorization policy 指定要用哪些驗證計畫時會用到。

Authenticate

Authenticate 負責建立請求中的使用者ID,若驗證成功會將使用者ID放在 authentication ticket 中並返回 AuthenticateResult。

Challenge

當尚未被授權的使用者嘗試存取需要授權才能存取的資源時,Authorization(授權)會呼叫 Challenge(IAuthenticationService.ChallengeAsync) 並告知使用者這個 Scheme 需要符合哪些驗證機制才可以存取該受保護的資源。

Forbid

當一個已通過驗證的使用者嘗試存取他無權限存取的資源時,Authorization(授權)會呼叫 Forbid(IAuthenticationService.ForbidAsync),forbid action 需要讓使用者知道他的操作是未經授權的,例如使用 cookie authentication scheme 時把使用者導向 forbidden 頁面,或是使用 JWT bearer scheme 時回覆403,或是使用自訂授權時將使用者導向可以要求或取得授權的頁面。

參考資料