AccessTokenController.php 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Http\Api\ChannelApi;
  4. use App\Models\AccessToken;
  5. use App\Services\AuthService;
  6. use Firebase\JWT\JWT;
  7. use Illuminate\Http\Request;
  8. use Illuminate\Http\Response;
  9. use Illuminate\Support\Facades\Log;
  10. use Illuminate\Support\Str;
  11. class AccessTokenController extends Controller
  12. {
  13. /**
  14. * 签出的 access token 有效期(秒)。7 天足够一次批量写入作业,
  15. * 又能把凭据泄漏的窗口限制在可接受范围内。
  16. */
  17. private const TOKEN_TTL = 60 * 60 * 24 * 7;
  18. /**
  19. * Display a listing of the resource.
  20. *
  21. * @return Response
  22. */
  23. public function index()
  24. {
  25. //
  26. }
  27. /**
  28. * Store a newly created resource in storage.
  29. *
  30. * @return Response
  31. */
  32. public function store(Request $request)
  33. {
  34. //
  35. $user = AuthService::current($request);
  36. if (! $user) {
  37. return $this->error(__('auth.failed'), [], 401);
  38. }
  39. $payload = $request->input('payload');
  40. $result = [];
  41. foreach ($payload as $key => $value) {
  42. // 鉴权
  43. switch ($value['res_type']) {
  44. case 'channel':
  45. if (! isset($value['power']) || ! isset($value['res_id'])) {
  46. continue 2;
  47. }
  48. if ($value['power'] === 'edit') {
  49. if (! ChannelApi::userCanEdit($user['user_uid'], $value['res_id'])) {
  50. continue 2;
  51. }
  52. } else {
  53. if (! ChannelApi::userCanRead($user['user_uid'], $value['res_id'])) {
  54. continue 2;
  55. }
  56. }
  57. break;
  58. default:
  59. continue 2;
  60. break;
  61. }
  62. // 获取token
  63. $token = AccessToken::firstOrNew(
  64. [
  65. 'res_type' => $value['res_type'],
  66. 'res_id' => $value['res_id'],
  67. ],
  68. [
  69. 'token' => (string) Str::uuid(),
  70. ]
  71. );
  72. if (! $token->exists) {
  73. $token->save();
  74. }
  75. // 有效期:payload 里不注入 exp 的话,签出的 token 永久有效,泄漏后无法失效
  76. $value['nbf'] = time();
  77. $value['exp'] = time() + self::TOKEN_TTL;
  78. try {
  79. $jwt = JWT::encode($value, $token->token.$token->token, 'HS512');
  80. } catch (\Exception $e) {
  81. Log::error('jwt', ['error' => $e]);
  82. continue;
  83. }
  84. $result[] = [
  85. 'payload' => $value,
  86. 'token' => $jwt,
  87. ];
  88. }
  89. return $this->ok(['rows' => $result, 'count' => count($result)]);
  90. }
  91. /**
  92. * Display the specified resource.
  93. *
  94. * @return Response
  95. */
  96. public function show(AccessToken $accessToken)
  97. {
  98. //
  99. }
  100. /**
  101. * Update the specified resource in storage.
  102. *
  103. * @return Response
  104. */
  105. public function update(Request $request, AccessToken $accessToken)
  106. {
  107. //
  108. }
  109. /**
  110. * Remove the specified resource from storage.
  111. *
  112. * @return Response
  113. */
  114. public function destroy(AccessToken $accessToken)
  115. {
  116. //
  117. }
  118. }