AuthenticateJwt.php 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <?php
  2. /*
  3. * This file is part of the Jiannei/lumen-api-starter.
  4. *
  5. * (c) Jiannei <longjian.huang@foxmail.com>
  6. *
  7. * This source file is subject to the MIT license that is bundled
  8. * with this source code in the file LICENSE.
  9. */
  10. namespace App\Http\Middleware;
  11. use App\Repositories\Enums\ResponseCodeEnum;
  12. use App\Support\Traits\LoginLimit;
  13. use Closure;
  14. use Illuminate\Auth\Access\AuthorizationException;
  15. use Illuminate\Http\Request;
  16. use Illuminate\Support\Facades\Auth;
  17. use Illuminate\Support\Facades\Log;
  18. use Tymon\JWTAuth\Exceptions\JWTException;
  19. use Tymon\JWTAuth\Exceptions\TokenExpiredException;
  20. use Tymon\JWTAuth\Exceptions\TokenInvalidException;
  21. use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;
  22. class Authenticate extends BaseMiddleware
  23. {
  24. use LoginLimit;
  25. /**
  26. * Handle an incoming request.
  27. *
  28. * @param Request $request
  29. * @param Closure $next
  30. * @param string|null $guard
  31. * @return mixed
  32. *
  33. * @throws AuthorizationException
  34. */
  35. public function handle($request, Closure $next, $guard = null)
  36. {
  37. Auth::setDefaultDriver($guard);
  38. try {
  39. // 检查此次请求中是否带有 token,如果没有则抛出异常。
  40. $this->checkForToken($request);
  41. } catch (TokenInvalidException $exception) {
  42. abort(ResponseCodeEnum::HTTP_UNAUTHORIZED, 'token有误');
  43. }
  44. //1. 格式通过,验证是否是专属于这个的token
  45. //获取当前守护的名称
  46. $guard = Auth::getDefaultDriver();
  47. Log::error("1");
  48. //使用 try 包裹,以捕捉 token 过期所抛出的 TokenExpiredException 异常
  49. //2. 此时进入的都是属于当前guard守护的token
  50. try {
  51. // 检测用户的登录状态,如果正常则通过
  52. if ($this->auth->parseToken()->authenticate()) {
  53. Log::error("2");
  54. $token = Auth::getToken();
  55. $user_id = $this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub'];
  56. //单机登录检查
  57. if (!$this->singleLoginCheck($token, $user_id, $guard)) {
  58. Log::error("3");
  59. abort(ResponseCodeEnum::HTTP_UNAUTHORIZED, '该账号已经再其他设备上登录');
  60. }
  61. Log::error("4");
  62. return $next($request);
  63. }
  64. Log::error("5");
  65. abort(ResponseCodeEnum::HTTP_UNAUTHORIZED, 'token过期,请重新登陆。');
  66. } catch (TokenExpiredException $exception) {
  67. // 3. 此处捕获到了 token 过期所抛出的 TokenExpiredException 异常,我们在这里需要做的是刷新该用户的 token 并将它添加到响应头中
  68. try {
  69. Log::error("6");
  70. // 刷新用户的 token
  71. $token = $this->auth->refresh();
  72. // 使用一次性登录以保证此次请求的成功
  73. $user_id = $this->auth->manager()->getPayloadFactory()->buildClaimsCollection()->toPlainArray()['sub'];
  74. Auth::onceUsingId($user_id);
  75. $this->singleLoginSetToken($user_id, $token, $guard);
  76. Log::error("7");
  77. return $this->setAuthenticationHeader($next($request), $token);
  78. } catch (JWTException $exception) {
  79. Log::error("8");
  80. Log::error($exception);
  81. // 如果捕获到此异常,即代表 refresh 也过期了,用户无法刷新令牌,需要重新登录。
  82. abort(ResponseCodeEnum::HTTP_UNAUTHORIZED, 'token令牌过期,请重新登陆。');
  83. }
  84. }
  85. Log::error("9");
  86. // 在响应头中返回新的 token
  87. abort(ResponseCodeEnum::HTTP_UNAUTHORIZED, '异常错误-Mead');
  88. }
  89. }