ResolvesCurrentUser.php 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. <?php
  2. namespace App\Http\Controllers\Concerns;
  3. use App\Http\Middleware\V3\Authenticate;
  4. use App\Services\AuthService;
  5. use Illuminate\Auth\AuthenticationException;
  6. use Illuminate\Http\Request;
  7. /**
  8. * 取当前登录用户——控制器的**胶水**动作,不是业务逻辑。
  9. *
  10. * 放在 trait 里而不是每个控制器各写一个 private 方法:控制器文件里除了入口方法
  11. * 不该再有第二个方法(见 v3-resource skill 硬规范第 5 条)。
  12. *
  13. * 挂了 `auth.v3` 中间件的路由,用户已经解好放在 request attributes 里,这里直接取,
  14. * 不重复解 JWT;没挂中间件的路由(如 tally 那种可选登录)走 {@see self::currentUserUid()}。
  15. */
  16. trait ResolvesCurrentUser
  17. {
  18. /**
  19. * 必须登录。挂了 `auth.v3` 的路由上它不可能抛——中间件已经挡过一道了。
  20. *
  21. * @return array{user_uid: string, user_id: int}
  22. *
  23. * @throws AuthenticationException 未登录(只会发生在忘挂中间件的路由上)
  24. */
  25. protected function currentUser(Request $request): array
  26. {
  27. $user = $request->attributes->get(Authenticate::USER);
  28. if (is_array($user)) {
  29. return $user;
  30. }
  31. throw new AuthenticationException;
  32. }
  33. /**
  34. * 可选登录:取到就返回 uuid,没登录返回 null,不抛异常。
  35. *
  36. * 与中间件一致只认 bearer——`AuthService::current()` 会回落去读 cookie,
  37. * 那是 v2 的旁路,v3 不走。
  38. */
  39. protected function currentUserUid(Request $request): ?string
  40. {
  41. if ($user = $request->attributes->get(Authenticate::USER)) {
  42. return $user['user_uid'];
  43. }
  44. if (! $request->bearerToken()) {
  45. return null;
  46. }
  47. return AuthService::current($request)['user_uid'] ?? null;
  48. }
  49. }