使用 Laravel Sanctum 對 Vue 應用進行授權

使用 Laravel Sanctum 對 Vue 應用進行授權

laravel Sanctum (以前稱為 Laravel Airlock), 于今年早些時候發布,是一個輕量級的擴展包,可以使得在單頁面應用或者本地移動應用上構建身份驗證的流程變得盡可能地簡單和輕松。在此之前,你要么使用基于 sessions 的 Web 中間件 ,要么使用外部集成的依賴包,如 Tymon 的 jwt-auth, 然而現在,你可以使用 Sanctum 來完成有狀態的身份驗證和基于 Token 身份驗證。

在這個簡短的測試中,我會向你展示如何讓運用 Laravel Sanctum 從 0 開始構建一個項目。 我們將創建一個虛擬 API,通過 Vue 組件對用戶進行身份驗證,并獲取與該登錄用戶相關聯的數據。

如果您想跳過書面教程,可以觀看我制作的 視頻

您也可以直接到 github 上查看完整源代碼,該源代碼位于 [代碼] this repository 。

立即學習前端免費學習筆記(深入)”;

準備就緒,接下來,讓我們一起盤它!

創建測試 API

我們需要做的第一件事是創建一個可以從中獲取數據的 API 接口。我構思了一個超級簡單的應用,用于檢索展示每個用戶的秘密列表。

我已經安裝了一個開箱即用的 Laravel 應用程序,并且將其跟 mysql 數據庫一起配置運行在我使用 Laravel docker setup 搭建的本地環境中。我要做的第一件事就是去為我們的 secret 創建一個模型類以及相關的遷移文件 ,這里我們可以很輕松地使用 artisan , 通過命令行來完成這些操作。

php?artisan?make:model?Secret?--migration

接下來,讓我們打開遷移文件,并且添加一些足以描述一個 secret 需要的數據列。 我認為我們需要的 (除了 Laravel 提供的默認 ID 和時間戳) 是一個用于跟用戶關聯的 user_id 整數字段 ,以及一個用于實實在在地保存用戶 secret 信息的字段。

Schema::create('secrets',?function?(Blueprint?$table)?{ ????$table->id(); ????$table->integer('user_id'); ????$table->text('secret'); ????$table->timestamps(); });

然后,接著運行數據庫遷移命令生成 users 和 secrets 兩個表。

php?artisan?migrate

我們需要對應用程序的兩個模型類進行一些簡單的修改,用于啟用兩個模型類之間的關聯關系,所以接下來讓我們打開這兩個模型類文件,并且開始修改 :

//?User.php public?function?secrets() { ????return?$this->hasMany('AppSecret'); } //?Secret.php public?function?user() { ????return?$this->belongsTo('AppUser'); }

我們 API 結構的最后一部分就是實際的路由和控制器。我們將僅僅訪問一條網頁路徑就可以展示出跟當前用戶的所有 secrets 信息。所以,我在? routes/api.php? 文件中添加了以下內容:

Route::get('/secrets',?'SecretController@index');

可以使用 Artisan 命令輕松創建此控制器:

php?artisan?make:controller?SecretController

打開剛剛創建的控制器,讓我們創建 index 方法,先返回所有的密鑰。因為 現在 我們還無法獲得經過身份驗證的用戶:

public?function?index() { ????return?AppSecret::all(); }

我們的虛擬 API 現在已經完成,來創建一些假用戶和密鑰吧。

填充數據庫

你可以輕松地直接進入數據庫并手動填充用戶,創建控制器和表單以供用戶輸入自己的數據,或者使用 Artisan tinker 來半自動創建用戶。我將跳過這些方法,使用內置的 Laravel 工廠為我們的用戶和密鑰生成假數據。

Laravel 帶有一個開箱即用的 UserFactory.php 類,用來生成假用戶。我們將為密鑰創建一個類似的工廠類。在終端中運行以下 Artisan 命令:

php?artisan?make:factory?SecretFactory?--model=Secret

打開生成的文件,我們只需用 user_id 和 secret 這兩個數據填充每個模型:

$factory->define(Secret::class,?function?(Faker?$faker)?{ ????return?[ ????????'user_id'?=>?1, ????????'secret'?=>?$faker->text ????]; });

你可能想知道為什么我們要在上面的片段中的 user_id 中使用硬編碼。因為我不想基于用戶數量隨機生成它,而是希望對其進行更多控制。稍后,我將告訴你當我們開始生成秘密時如何覆蓋它。

讓我們從創建幾個假用戶開始。通過從站點根目錄運行 php artisan tinker 命令來打開 Tinker Shell. 打開后,我們可以通過兩次運行 global factory helper 來創建兩個用戶:

factory(AppUser::class)->create();?//?與make不同,create?將我們的用戶保存在數據庫中

Now that we have them generated, let’s create our secrets. I’m going to run the following in the tinker shell twice to create two for user_id 1:

現在我們已經生成了它們,讓我們創建我們的密鑰。我在 tinker 中運行以下命令兩次,為 user_id 1 創建兩個密鑰:

factory(AppSecret::class)->create();

但是如果第二個密鑰擁有不同 ID 的用戶呢?覆蓋工廠類中的任何值都很容易,我們要做的就是將覆蓋數組傳遞給 create() 方法。因此,我們將運行兩次以下命令,為第二個假用戶創建兩個密鑰:

factory(AppSecret::class)->create(['user_id'?=>?2]);

我們的數據庫中填充了足夠的假數據之后,讓我們繼續安裝和準備 Laravel Sanctum 軟件包。

安裝 Laravel Sanctum

安裝輕而易舉,可以通過在終端中運行一些命令來完成。首先,讓我們使用 composer 安裝該軟件包:

composer?require?laravel/sanctum

接下來運行以下命令發布遷移文件(并運行遷移):

php?artisan?vendor:publish?--provider="LaravelSanctumSanctumServiceProvider" php?artisan?migrate

Sanctum 安裝的最后一部分要求我們修改 apphttpKernel.php 文件以包含一個中間件,該中間件會將 Laravel 的會話 Cookie 注入到我們的應用程序前端中。這最終將使我們能夠以經過身份驗證的用戶身份傳遞和檢索數據:

'api'?=>?[ ????EnsureFrontendRequestsAreStateful::class, ????'throttle:60,1' ]

現在,我們可以進入應用程序的前端了!

構建前端

從 Laravel 7 開始,前端和身份驗證模板已從主程序包中剝離,可以單獨安裝。為了進行演示,我們將使用它和 Vue 來構建前端。

在應用程序的根目錄運行以下命令將幫助我們配置環境:

composer?require?laravel/ui php?artisan?ui?vue?--auth npm?install?&&?npm?run?dev

上面的命令做了三件事:

使用 Composer 安裝 Laravel UI 軟件包

生成 JS/UI 文件、身份驗證模板和 package.json 修改

安裝前端依賴項并編譯開發環境的 JS/css 文件

我會把 welcome.blade.php 文件里的所有內容拷貝到 app.blade.php 文件里,然后把外部 div 里的內容刪掉并添加一個 id=”app” 屬性。這將是我們 Vue 應用程序的掛載點,如剛才生成的 app.js 文件中所述。

讓我們創建 Vue 組件,該組件將保存我們的登錄表單并顯示一些 secret.

創建 Vue 組件

在此之前,我們可以通過命令: php artisan ui vue 來生快速成我們的前端代碼,它默認會生成一個 resources/js/components/ExampleComponent.vue 組件事例。好了,現在讓我們創建新的組件:SecretComponent.vue,它的代碼如下:

<template></template><script> export default {     data() {         return {             secrets: [],             formData: {                 email: &#39;&#39;,                 password: &#39;&#39;             }         }     } } </script>

這里有兩個字段返回,其中 secrets 字段是個數組,還有一個用戶存儲 email 和 password 字段的 formData 對象

下面,我們將在 template 標簽內構件我們的登錄表單。

<template> ????<div> ????????<div> ????????????<form> ????????????????<div> ????????????????????<input> ????????????????</div> ????????????????<div> ????????????????????<input> ????????????????</div> ????????????????<div> ????????????????????<button>Sign?In</button> ????????????????</div> ????????????</form> ????????</div> ????</div> </template>

好了,一個登錄表單創建完成,它可能看起來像下面這樣:

使用 Laravel Sanctum 對 Vue 應用進行授權

在上面代碼中,我們禁用了 form 表單的默認提交操作,并將它移交給 Vue 的 Submit 來處里。現在我們創建 handleLogin 方法來處理用戶的登錄請求:

<script> export default {     data() {         return {             secrets: [],             formData: {                 email: &#39;&#39;,                 password: &#39;&#39;             }         }     },     methods: {         handleLogin() {             // 處理登錄請求         }     } } </script>

最后,不要忘記將我們的組件注冊到 resources/js/app.js 文件中:

Vue.component('secret-component',?require('./components/SecretComponent.vue).default);

然后在 app.blade.php 中使用該組件。現在我們可以通過 handleLogin() 方法驗證用戶登錄操作了。

用戶驗證

如果看過 Laravel Sanctum documentation 這篇文章,你應該知道 SPA 單頁應用的 csrf 保護實現方式,你需要先請求 /sanctum/csrf-cookie 以獲取 csrf token。

然后,我們請求 /login 路由,并將我們的 email 和 password 字段傳遞給后端接口處理。

現在讓我們在 handleLogin() 方法中實現上面的需求:

handleLogin()?{ ????axios.get('/sanctum/csrf-cookie').then(response?=&gt;?{ ????????axios.post('/login',?this.formData).then(response?=&gt;?{ ????????????console.log('登錄成功!'); ????????}).catch(error?=&gt;?console.log(error));?//?如果驗證不匹配 ????}); }

現在,使用當我們輸入相應的信息你會發現流程已經走通。每個請求都會受到 csrf 保護,并發送登錄接口所需要的 email 與 password 字段,即使現在沒有響應數據,我的程序依然會通過 promise 繼續執行,而不會崩潰。

接下來要做什么?讓我們完成登錄操作吧!

用戶檢索

在我們的 Vue 組件中,繼續創建名為 getSecrets() 方法,該方法是用戶登陸成功之后,獲取用戶 secrets ,通常我們會得到一個 secrets 數組,之后我們將我們的得到的新的數組替換組件中原有的數組。

打當用戶登錄成功之后,我們調用 getSecrets() 函數以完成后續操作。

handleLogin()?{ ????axios.get('/sanctum/csrf-cookie').then(response?=&gt;?{ ????????axios.post('/login',?this.formData).then(response?=&gt;?{ ????????????this.getSecrets(); ????????}).catch(error?=&gt;?console.log(error));?//?credentials?didn't?match ????}); }, getSecrets()?{ ????axios.get('/api/secrets').then(response?=&gt;?this.secrets?=?response.data); }

但是,現在程序中我們返回的是所有用戶 secrets。所以我們需要在 index() 方修改它,以得到正確的數據:

public?function?index(Request?$request) { ????return?$request-&gt;user()-&gt;secrets; }

在登錄成功之后,所有需要用戶驗證的接口中的請求頭中都會包含 laravel_session cookie,這樣 Sanctum 可以通過該 cookie 來確定并關聯當前請求的用戶。

之后,既可以使用 $request 對象來獲取用戶的全部信息了,然后我們將 secret 信息與用戶關聯,并將數據返回。

最后我們將數據格式化、脫敏之后呈現給用戶:

<template> ????<div> ????????<div> ????????????<div> ????????????????<strong></strong>?-?created?at?<span></span> ????????????</div> ????????</div> ????</div> </template>

現在我們刷新應用,并使用我們 fake 的用戶數據登錄,就可以看到以下頁面了:

使用 Laravel Sanctum 對 Vue 應用進行授權

至此,一個 SPA 單頁應用的登錄操作完成。

總結和后續

我僅僅剛開始接觸并使用該擴展,如果使用以上方式驗證用戶,則之后所有需要用戶信息的接口可以實現像傳統 web 應用的登錄操作一樣,每個請求都會攜帶用戶狀態。

當然,你也可以用 token 令牌的方式實現 SPA 單頁應用的身份驗證,移動以及桌面應用。俗話說的好條條大路通羅馬。該文章只是圍繞 documentation 該擴展展開的討論與實踐。

希望本文能給您的開發帶來方便與啟發。

推薦教程:《PHP教程

? 版權聲明
THE END
喜歡就支持一下吧
點贊10 分享