Token.php 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\Utils\Encrypt;
  4. use App\Master\Enum\RedisKeyEnum;
  5. use App\Utils\RedisUtil;
  6. use Hyperf\Config\Annotation\Value;
  7. use Hyperf\Coroutine\Coroutine;
  8. class Token
  9. {
  10. /**
  11. * Token 配置信息
  12. * @var array
  13. */
  14. #[Value("token.default")]
  15. protected array $config;
  16. private static $instances = [];
  17. /**
  18. * 协程单例模式处理
  19. * @return mixed|self
  20. */
  21. public static function getInstance()
  22. {
  23. $instanceName = Coroutine::id() . uniqid();//协程id&唯一id组成
  24. if (!isset(self::$instances[$instanceName])) {
  25. self::$instances[$instanceName] = new self();
  26. Coroutine::defer(function () use ($instanceName) {
  27. unset(self::$instances[$instanceName]);
  28. });
  29. }
  30. return self::$instances[$instanceName];
  31. }
  32. /**
  33. * 创建token
  34. * @param array $data
  35. * @return string
  36. * @throws \Exception
  37. */
  38. public function create(array $data): string
  39. {
  40. $data = array_merge($data, [
  41. 'iat' => time(),// 签发时间
  42. 'exp' => time() + $this->config['expire'],// 过期时间
  43. ]);
  44. $dataJson = json_encode($data, JSON_UNESCAPED_UNICODE);
  45. $token = Aes::encode($dataJson, $this->config['key']);
  46. // 校验唯一token,单点登录
  47. if ($this->config['sso'] === true) {
  48. $token_key = (string)key($data);
  49. $token_id = (string)reset($data);
  50. RedisUtil::getInstance(RedisKeyEnum::TOKEN_ONCE, $token_key, $token_id)->setex($token, $this->config['expire']);
  51. }
  52. return $token;
  53. }
  54. /**
  55. * 验证token是否有效
  56. * @param string $token
  57. * @return false|mixed
  58. * @throws \Exception
  59. */
  60. public function check(string $token)
  61. {
  62. //验证token
  63. if (!$data = Aes::decode($token, $this->config['key'])) {
  64. return false;
  65. }
  66. $data = json_decode($data, true);
  67. // 校验唯一token,单点登录
  68. if ($this->config['sso'] === true) {
  69. $token_key = (string)key($data);
  70. $token_id = (string)reset($data);
  71. if (!$userToken = RedisUtil::getInstance(RedisKeyEnum::TOKEN_ONCE, $token_key, $token_id)->get()) {
  72. return false;
  73. }
  74. if ($userToken != $token) {
  75. return false;
  76. }
  77. }
  78. return $data;
  79. }
  80. /**
  81. * 删除token
  82. * 仅开启单点登录时 可用
  83. * @param array $data 生成token时传递的参数
  84. * @return bool
  85. * @throws \Exception
  86. */
  87. public function remove(array $data)
  88. {
  89. // 单点登录 删除登录状态
  90. if ($this->config['sso'] === true) {
  91. $token_key = (string)key($data);
  92. $token_id = (string)reset($data);
  93. //验证token
  94. if (!RedisUtil::getInstance(RedisKeyEnum::TOKEN_ONCE, $token_key, $token_id)->del()) {
  95. return false;
  96. }
  97. }
  98. return true;
  99. }
  100. }