passport+Auth2.0认证

参考链接

Laravel 的 API 认证系统 Passport 三部曲(一、passport安装+配置)

Laravel 的 API 认证系统 Passport

引言

  1. 在使用前要先了解Auth2.0的使用方式和原理Laravel 的用户认证系统
  2. passport是专门做api令牌授权的工具,这里有个问题是他不像auth一样可以定义多个guard来区分不同平台走不同的auth认证模块,他默认只走guard=api这个api认证模块。

密码授权令牌的获取

  • 请求令牌
    创建密码授权的客户端后,就可以通过向用户的电子邮件地址和密码向 /oauth/token 路由发出 POST 请求来获取访问令牌。而该路由已经由 Passport::routes 方法注册,因此不需要手动定义它。如果请求成功,会在服务端返回的 JSON 响应中收到一个 access_token 和 refresh_token:

    1. $http = new GuzzleHttp\Client;
    2. $response = $http->post('http://your-app.com/oauth/token', [
    3. 'form_params' => [
    4. 'grant_type' => 'password',
    5. 'client_id' => 'client-id',
    6. 'client_secret' => 'client-secret',
    7. 'username' => 'taylor@laravel.com',
    8. 'password' => 'my-password',
    9. 'scope' => '',
    10. ],
    11. ]);
    12. return json_decode((string) $response->getBody(), true);

私人访问令牌

在你的应用程序发布个人访问令牌之前,你需要在 passport:client 命令后带上 —personal 参数来创建对应的客户端。如果你已经运行了 passport:install 命令,则无需再运行此命令:

  1. php artisan passport:client --personal

创建个人访问客户端后,你可以使用 User 模型实例上的 createToken 方法来为给定用户发布令牌。
createToken 方法接受令牌的名称作为其第一个参数和可选的 作用域 数组作为其第二个参数:

  1. $user = App\User::find(1);
  2. // Creating a token without scopes...
  3. $token = $user->createToken('Token Name')->accessToken;
  4. // Creating a token with scopes...
  5. $token = $user->createToken('My Token', ['place-orders'])->accessToken;

注意: 由于passport默认只可以走一个guard认证,当多平台的时候,可以使用auth2.0来辅助操作,首先使用Auth2.0验证该平台对应的guard(当然,驱动使用session))下其账号密码是否正确,验证通过之后再获取该用户实例并给予私人访问令牌,这样就做到了不同平台的令牌生成)

验证令牌

  • 通过中间件

    Passport 包含一个 验证保护机制 可以验证请求中传入的访问令牌。配置 api 的看守器使用 passport 驱动程序后,只需要在需要有效访问令牌的任何路由上指定 auth:api 中间件:

    1. Route::get('/user', function () {
    2. //
    3. })->middleware('auth:api');
  • 我们实现方式

    由于passport只可以走api一个guard验证,也就是只可以走一个用户授权表,这里我们多平台多登陆授权表则只用上面的验证登陆肯定就不对了,如上所说我们结合auth2.0来进行分平台进行验证。

    1. 首先创建一个AuthApi中间键
    2. 在/app/Http/Kernel.php中注册AuthApi中间键

      eg:

      1. public function handle($request, Closure $next, $guard = null)
      2. {
      3. if (empty(Auth::guard($guard)->user())) {
      4. return response()->json(["message" => "Unauthenticated."], 401);
      5. }
      6. return $next($request);
      7. }

      protected $routeMiddleware = [
      ‘apiAuth’ => ApiAuth::class,
      ……
      ];

    3. 使用的时候比如要使用guard=home的验证令牌,则中间件为“apiAuth:home”即可

注销登录、定期检查过期token,销毁旧的token

  • 注销登录

    eg:

    1. /**
    2. * 登出程序操作.
    3. *
    4. * @return \Illuminate\Http\Response
    5. */
    6. public function logout()
    7. {
    8. $user = $this->guard()->user();
    9. if (empty($user)) {
    10. return $this->sendError('暂未登录', ['暂未登录'], 403);
    11. }
    12. // 获取当前登陆用户的access_token的id
    13. $accessToken = $user->access_token;
    14. // 找到这条access_token并且将其删除
    15. $token = Token::find($accessToken);
    16. if (empty($token)) {
    17. return $this->sendError('暂无有效令牌', ['暂无有效令牌'], 403);
    18. }
    19. if (!empty($token->delete())) {
    20. return $this->sendResponse([], '退出成功!');
    21. } else {
    22. return $this->sendError('退出失败', ['退出失败'], 500);
    23. }
    24. }
  • 定期检查过期token(官方文档没给,个人做的优化)

    • 创建token生成事件的监听器来处理该用户当前客户端下的所有失效的token

      在“/app/Providers/EventServiceProvider.php”中的“$listen”数组中添加

      1. // 生成token,检查失效的进行删除
      2. 'Laravel\Passport\Events\AccessTokenCreated' => [
      3. 'App\Listeners\RevokeOldTokens',
      4. ],

      终端执行:

      1. php artisan event:generate

      提示:”Events and listeners generated successfully!”代表创建成功了

    • 执行删除失效token操作

      在 ‘App\Listeners\RevokeOldTokens’的handle方法中执行删除失效token操作

      1. Token::where('id', '!=', $event->tokenId)
      2. ->where('user_id', $event->userId)
      3. ->where('client_id', $event->clientId)
      4. ->where('expires_at', '<', Carbon::now())
      5. ->orWhere('revoked', true)
      6. ->delete();

您的支持是对我最大的鼓励!

分类: laravel

标签:   passport