Laravel 的 API 认证系统 Passport 三部曲(二、passport的具体使用)
参考链接
Laravel 的 API 认证系统 Passport 三部曲(一、passport安装+配置)
引言
- 在使用前要先了解Auth2.0的使用方式和原理Laravel 的用户认证系统
- passport是专门做api令牌授权的工具,这里有个问题是他不像auth一样可以定义多个guard来区分不同平台走不同的auth认证模块,他默认只走guard=api这个api认证模块。
密码授权令牌的获取
-
请求令牌
创建密码授权的客户端后,就可以通过向用户的电子邮件地址和密码向 /oauth/token 路由发出 POST 请求来获取访问令牌。而该路由已经由 Passport::routes 方法注册,因此不需要手动定义它。如果请求成功,会在服务端返回的 JSON 响应中收到一个 access_token 和 refresh_token:$http = new GuzzleHttp\Client; $response = $http->post('http://your-app.com/oauth/token', [ 'form_params' => [ 'grant_type' => 'password', 'client_id' => 'client-id', 'client_secret' => 'client-secret', 'username' => 'taylor@laravel.com', 'password' => 'my-password', 'scope' => '', ], ]); return json_decode((string) $response->getBody(), true);
私人访问令牌
在你的应用程序发布个人访问令牌之前,你需要在 passport:client 命令后带上 --personal 参数来创建对应的客户端。如果你已经运行了 passport:install 命令,则无需再运行此命令:
php artisan passport:client --personal
创建个人访问客户端后,你可以使用 User 模型实例上的 createToken 方法来为给定用户发布令牌。
createToken 方法接受令牌的名称作为其第一个参数和可选的 作用域 数组作为其第二个参数:
$user = App\User::find(1);
// Creating a token without scopes...
$token = $user->createToken('Token Name')->accessToken;
// Creating a token with scopes...
$token = $user->createToken('My Token', ['place-orders'])->accessToken;
注意: 由于passport默认只可以走一个guard认证,当多平台的时候,可以使用auth2.0来辅助操作,首先使用Auth2.0验证该平台对应的guard(当然,驱动使用session))下其账号密码是否正确,验证通过之后再获取该用户实例并给予私人访问令牌,这样就做到了不同平台的令牌生成)
验证令牌
-
通过中间件
Passport 包含一个 验证保护机制 可以验证请求中传入的访问令牌。配置 api 的看守器使用 passport 驱动程序后,只需要在需要有效访问令牌的任何路由上指定 auth:api 中间件:
Route::get('/user', function () { // })->middleware('auth:api');
-
我们实现方式
由于passport只可以走api一个guard验证,也就是只可以走一个用户授权表,这里我们多平台多登陆授权表则只用上面的验证登陆肯定就不对了,如上所说我们结合auth2.0来进行分平台进行验证。
- 首先创建一个AuthApi中间键
- 在/app/Http/Kernel.php中注册AuthApi中间键
eg:
public function handle($request, Closure $next, $guard = null) { if (empty(Auth::guard($guard)->user())) { return response()->json(["message" => "Unauthenticated."], 401); } return $next($request); }
protected $routeMiddleware = [
'apiAuth' => ApiAuth::class,
......
];- 使用的时候比如要使用guard=home的验证令牌,则中间件为“apiAuth:home”即可
注销登录、定期检查过期token,销毁旧的token
-
注销登录
eg:
/** * 登出程序操作. * * @return \Illuminate\Http\Response */ public function logout() { $user = $this->guard()->user(); if (empty($user)) { return $this->sendError('暂未登录', ['暂未登录'], 403); } // 获取当前登陆用户的access_token的id $accessToken = $user->access_token; // 找到这条access_token并且将其删除 $token = Token::find($accessToken); if (empty($token)) { return $this->sendError('暂无有效令牌', ['暂无有效令牌'], 403); } if (!empty($token->delete())) { return $this->sendResponse([], '退出成功!'); } else { return $this->sendError('退出失败', ['退出失败'], 500); } }
-
定期检查过期token(官方文档没给,个人做的优化)
-
创建token生成事件的监听器来处理该用户当前客户端下的所有失效的token
在“/app/Providers/EventServiceProvider.php”中的“$listen”数组中添加
// 生成token,检查失效的进行删除 'Laravel\Passport\Events\AccessTokenCreated' => [ 'App\Listeners\RevokeOldTokens', ],
终端执行:
php artisan event:generate
提示:"Events and listeners generated successfully!"代表创建成功了
-
执行删除失效token操作
在 'App\Listeners\RevokeOldTokens'的handle方法中执行删除失效token操作
Token::where('id', '!=', $event->tokenId) ->where('user_id', $event->userId) ->where('client_id', $event->clientId) ->where('expires_at', '<', Carbon::now()) ->orWhere('revoked', true) ->delete();
-