記錄一次Authorization 異常的插曲:
api.php有如下配置:
Route::middleware('auth:api')->post('/userfollowOrUnFollowCelebrity', 'FollowController@followOrUnFollowCelebrity');
FollowController構造函數及對應方法如下:
public function __construct() { $this->middleware('auth')->except(['getFollowersData', 'followOrUnFollowCelebrity', 'getUserFollowedUsers']); $this->middleware('auth:api')->only(['getFollowersData', 'followOrUnFollowCelebrity', 'getUserFollowedUsers']); } public function followOrUnFollowCelebrity(Request $request) { $celebrity_id = $request->get('celebrity'); if (is_null($celebrity_id)) { return response()->json(json_encode(['no available celebrity id'])); } $celebrity = User::query()->where('id', $celebrity_id)->firstOrFail(); if (Auth::guard('api')->check()) { } else { }
auth.php中guards如下:
'guards' => [ 'web' => [ 'driver' => 'session', 'provider' => 'users', ], 'api' => [ 'driver' => 'token', 'provider' => 'users', 'hash' => true, ], ],
數據庫中用戶已經有api_token 但是死活驗證不成功一直報 message: "Unauthenticated."
查了資料看到:
https://laravel.com/docs/5.8/api-authentication
https://rickkuilman.nl/blog/hashing-api-tokens-for-improved-security/
后 發現 原來用戶表里我設置的api_token時 直接設置 忘記了hash存入;
那么
’hash’=>false
就可以了。
更安全的參照下面:
In order to make the login function working again, we have to run the hash function once on all the users. This can be done quickly by running the following command in php artisan tinker:
use App\User;User::all()->each(function ($user) { $user->update(['api_token' => hash('sha256', $user->api_token)]); });有時候不起左右:
執行:
php artisan config:clear
From now on the user's API token is safely stored away in the database.
https://learnku.com/docs/laravel/6.x/api-authentication/5429
注意如果使用hash的api_token,那么就不要在RegisterController中生成API token,而應該在登錄或者刷新頁面的同時,請求生成一個新的Api Token,生成后,網站數據庫中存儲一個副本然后返回token文本值給前端視圖,閱后即焚,在該頁面的post 或者ajax請求的時候上傳比對,下次頁面刷新或者登錄的時候,又下一次生成一次性的Api Token存入數據庫並返回一個json 給前端。
比如ApiTokenController:
<?php namespace App\Http\Controllers; use Illuminate\Http\Request; class ApiTokenController extends Controller { // public function update(Request $request) { $token = str_random(80); auth()->user()->forceFill([ 'api_token' => hash('sha256', $token), ])->save(); return ['token' => $token]; } }
注意這個也是生成一個hash結果然后存入數據庫,前端收到的也是這個,然后如果api中
'api' => [ 'driver' => 'token', 'provider' => 'users', 'hash' => true, ], 還是’hash’=>true那么又成了數據庫中的值比對前端傳來的值再hash一次的比對,又會false,這個邏輯的具體實現,這里暫時不做,因為更好的是使用passport 以及 jwt。