[ Laravel 5.8 文件 ] 安全系列 —— API 認證
簡介
預設情況下,Laravel 通過為應用中的每個使用者分配一個隨機的令牌這種方式提供了一個非常簡單的 API 認證解決方案。在配置檔案config/auth.php
中,預設已經定義了一個api
守衛(guard)並且對應的驅動是token
。該驅動負責檢查進入應用的請求上的 API 令牌,並驗證是否與分配給使用者的令牌值相同(分配給使用者的令牌一般儲存在資料庫中)。
注:儘管 Laravel 提供了上面這個簡單的、基於令牌的 API 認證,我們還是強烈推薦你在生產環境中使用基於Laravel Passport 實現的 API 認證。
配置
資料庫準備
使用token
驅動前,需要建立一個遷移用來新增api_token
欄位到users
資料表:
Schema::table('users', function ($table) { $table->string('api_token', 80)->after('password') ->unique() ->nullable() ->default(null); });
遷移檔案建立之後,執行 Artisan 命令php artisan migrate
讓其生效。
生成令牌
api_token
欄位新增到users
資料表之後,就可以分配隨機的 API令牌給每個註冊使用者了。你需要在使用者註冊期間User
模型建立之際分配這些令牌。如果你使用的是 Artisan 命令make:auth
生成的認證腳手架程式碼,該操作可以在RegisterController
控制器的create
方法中完成:
use Illuminate\Support\Str; use Illuminate\Support\Facades\Hash; /** * Create a new user instance after a valid registration. * * @paramarray$data * @return \App\User */ protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), 'api_token' => Str::random(60), ]); }
雜湊令牌
在上述例子中,API 令牌以明文方式儲存在資料庫裡,如果你想要使用諸如 SHA-256 雜湊演算法計算令牌的雜湊值之後再儲存,可以在配置檔案config/auth.php
中的api
配置項中設定hash
值為true
來實現:
'api' => [ 'driver' => 'token', 'provider' => 'users', 'hash' => true, ],
生成雜湊令牌
如果要使用雜湊後的 API 令牌,就不要在使用者註冊期間生成 API 令牌。取而代之,你需要在應用中實現自己的 API 令牌管理頁面,這個頁面應該可以允許使用者初始化和重新整理他們自己的 API 令牌。當一個使用者發起一個初始化或重新整理令牌的請求時,後臺需要在資料庫中儲存這個令牌的雜湊值備份,並返回令牌的原始值到檢視/前臺客戶端做一次性展示。
舉個例子,用於為給定使用者初始化/重新整理令牌並返回令牌原始值 JSON 響應的控制器方法應該像下面這段程式碼這樣:
<?php namespace App\Http\Controllers; use Illuminate\Support\Str; use Illuminate\Http\Request; class ApiTokenController extends Controller { /** * Update the authenticated user's API token. * * @param\Illuminate\Http\Request$request * @return array */ public function update(Request $request) { $token = Str::random(60); $request->user()->forceFill([ 'api_token' => hash('sha256', $token), ])->save(); return ['token' => $token]; } }
注:由於上面這個例子中的 API 令牌有足夠的熵,建立「彩虹表」來暴力查詢雜湊令牌的原始值基本是徒勞的,所以也就不需要使用類似於bcrypt
這種雜湊方法。
路由保護
Laravel 內建了可以自動驗證輸入請求中的 API 令牌的認證守衛,你只需要在需要驗證訪問令牌的路由上應用auth:api
中介軟體即可:
use Illuminate\Http\Request; Route::middleware('auth:api')->get('/user', function(Request $request) { return $request->user(); });
在請求中傳遞令牌
有多種方式傳遞 API 令牌到應用,下面我們將一一介紹並通過 Guzzle HTTP 庫來演示它們的使用。你可以基於自己的需求選用其中任何一種方式。
查詢字串
應用的 API 消費者可以通過api_token
查詢字串指定他們的令牌值:
$response = $client->request('GET', '/api/user?api_token='.$token);
表單請求資料
應用的 API 消費者還可以在請求表單引數中通過api_token
欄位引入 API 令牌:
$response = $client->request('POST', '/api/user', [ 'headers' => [ 'Accept' => 'application/json', ], 'form_params' => [ 'api_token' => $token, ], ]);
Bearer Token
最後,應用的 API 消費者還可以在請求的Authorization
頭中以Bearer
令牌的方式提供他們的 API 令牌值:
$response = $client->request('POST', '/api/user', [ 'headers' => [ 'Authorization' => 'Bearer '.$token, 'Accept' => 'application/json', ], ]);