Lumen Auth、Guard、User 身份驗證詳解(一)- Authentication 文件忙什麼

Wake Liu
興趣使然的程式猿
6 min readAug 4, 2019
Lumen Auth、Guard、User 身份驗證詳解 文章目錄:(一)Authentication 文件忙什麼
(二)你的架構不是你的架構
(三)全部的流程都解開了!(上)

一般 Lumen 開發者在剛開始處理身份驗證時,除了用關鍵字餵 Google,最常就是跑去翻官網的 Authentication 文件,然後就會像我一樣,一臉期待地進來,又滿頭霧水地離開。如果沒有 Laravel 經驗而直接接觸 Lumen 的開發者,這份文件真的省略到讓人毫無頭緒。

在開始詳細說明整套身份驗證架構前,我先概略解釋 Authentication 這短短一頁到底在講什麼。

Authentication Service Provider

現在是 DI(Dependency Injection)模式普及的年代,使用服務前要先註冊已經是多數 PHP 開發者的反射動作。然而大部分人照著官方 Authentication 文件註冊完 AuthServiceProvider 後,往下文一看就茫然了,這段語意不明的 code 是從哪冒出來的?

$this->app['auth']->viaRequest ('api', function ($request) {  // Return User or null...});

每個字好像都看得懂,又好像看的不太懂;是的我們知道它是寫在 AuthServiceProvider boot funcion 中,當服務啟動時運作的一段程式碼,但具體來說是在做什麼?

先等等…不要急,讓我們把視角拉遠,巨大的疑惑放在一邊;整個官方 Authentication 文件在描述的流程,如果用白話文來講大概就是:

  1. 在系統中註冊一個 身份驗證的服務
  2. 當服務啟動時,建立一個 針對連線請求做檢查的守門員
  3. 在檢查連線請求的過程中,如果要辨識使用者,可以建立一個 回傳用的使用者物件
  4. 在驗證的中介層 Authenticate Middleware 當中,呼叫已經建立好的 守門員 進行身份檢查。

現在,我暫時透過簡單的 QA 形式回答常見的疑惑;完整的細節和流程留在後續說明。

Authentication 文件 Q&A

👉 viaRequest 函式從哪來的?是指要檢查連線請求嗎?

是也不是。從程式註釋當中來看的話, viaRequest 這個函式的意思比起 via Request ,更像是 via RequestGuard ,透過 請求守門員 RequestGuard 來處理連線請求。RequestGuard 物件會在 viaRequest 函式呼叫時自動被建立。

👉 viaRequest ('api', …) 當中的 api 是…?

這個 api 和你在寫的 API 其實沒有直接關聯,它是可以自訂的 auth driver 的索引鍵值,理論上你可以替換成任何字,但要記得在 config/auth.php 做對應的修改。

👉 viaRequest (…, callback) 後面的 callback 是…?

這裡的 callback 是用來 回傳使用者物件 的回呼函式,在官方文件此一架構中,回傳的使用者物件一共有兩個用途:

  1. 讓 RequestGuard 判斷連線進來的是 使用者訪客(回傳 null 會被判斷為 guest)。
  2. 當使用者執行 $request->user () 時,呼叫此一函式取得 使用者物件

👉 app['auth'] 又是哪來的?

如你所知,ServiceProvider 裡的 $this->app 就是 Lumen Application 物件本身,而 app['auth'] 是一個 在存取時會自動被產生出來AuthManager 物件,除非你提前存取過了 app['auth'],不然這裡應該是初次實例化的地方,你可以在這段 Code 的前後用 isset ($this->app['auth']) 試看看。

👉 所以 $this->app['auth']->viaRequest ('api', callback) 這整段的意義是?

簡單來說,就是當 AuthServiceProvider 啟動時,會透過自動建立的 AuthManager 物件,產生一個 RequestGuard 的 auth driver,然後指派一個用來 判斷並取得使用者物件 的回呼函式給它。

👉 真正執行的身份驗證的程式段到底在哪?

以官方 Authentication 文件的架構來說共有兩個地方。其一是 Authenticate Middlewarehandle 函式內:

if ($this->auth->guard ($guard)->guest ()) {  return response ('Unauthorized.', 401);}

這裡呼叫了 Guard(預設的 api Guard)來判斷連線身份是否為訪客,如是,則拒絕授權。

其二是 AuthServiceProviderboot 函式內:

$this->app['auth']->viaRequest ('api', function ($request) {  // Return User or null...});

這裡定義的 回傳使用者物件 callback 如果傳回了 null, guard($guard)->guest() 就會為 true — 被視為是 guest 而拒絕授權,相反的若傳回了使用者,就可以安然通過。

結語

如果這篇概文章有幫助你多瞭解官方 Authentication 文件,小弟我覺得十分榮幸;但倘若還是無法解開你的疑惑,沒關係,後續我會盡可能完整詳細地拆解整套身份驗證運作機制,希望到時能再帶給你另一番想法。

--

--