Laravel API Token 验证
记录一次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。