'int', 'token_guid' => 'string', 'user_guid' => 'string', 'token_menu' => 'json', 'token_api' => 'json', 'token_exp_time' => 'datetime', 'token_content' => 'string', 'token_create_time' => 'datetime', 'token_update_time' => 'datetime', ]; // json数据字段 protected $json = ['token_menu', 'token_api']; // 设置JSON数据返回数组 protected $jsonAssoc = true; // 开启自动写入时间戳字段 protected $autoWriteTimestamp = 'datetime'; // 创建时间 protected $createTime = 'token_create_time'; // 修改时间 protected $updateTime = 'token_update_time'; /** * 当前用户 * * @var User */ private static $user = null; /** * 当前model * * @var self */ private static $current = null; /** * 用户 * * @date 2022-02-22 * @example * @author admin * @since 1.0.0 */ public function user(): hasOne { return $this->hasOne(User::class, 'user_guid', 'user_guid'); } /** * 设置过期时间 * * @param mixed $value * @date 2022-02-22 * @example * @author admin * @since 1.0.0 */ public function setTokenExpTimeAttr($value): string { return date('Y-m-d H:i:s', $value); } /** * 判断是否过期 * * @return boolean * @date 2022-12-27 * @example * @author admin * @since 1.0.0 */ public function getIsExpAttr(): bool { return time() >= $this->token_exp_timestamp; } /** * 获取过期时间戳 * * @return integer * @date 2022-12-27 * @example * @author admin * @since 1.0.0 */ public function getTokenExpTimestampAttr(): int { return strtotime($this->token_exp_time); } /** * 新增前 * * @param self $model * @return void * @date 2022-12-27 * @example * @author admin * @since 1.0.0 */ public static function onBeforeInsert(self $model): void { $model->token_content = $model->generateContent(); $model->token_guid = self::generateGuid(); } /** * 登陆 * 如果当前存在有效token 更新过期时间 * 如果token已过期 更新token和过期时间 * 如果不存在token 新增数据 * * @param string $guid 用户id * @param array $options 配置项 * @param int $options[expTime] 过期时间(时间戳) 不传默认两小时 * @param array $options[menu] 菜单 * @param int $options[api] 接口 * @date 2022-02-22 * @example * @author admin * @since 1.0.0 */ public static function login(string $guid, array $options = []): self { $expTime = 0; $menu = []; $api = []; if (is_array($options)) { $expTime = Arr::get($options, 'expTime', 0); $menu = Arr::get($options, 'menu', []); $api = Arr::get($options, 'api', []); } if ($expTime == 0) { $expTime = time() + (24 * 60 * 60); } $data = [ 'token_exp_time' => $expTime ]; if ($menu) { $data['token_menu'] = $menu; } if ($api) { $data['token_api'] = $api; } /** * @var Token */ $model = self::where([ 'user_guid' => $guid, ])->find(); // 数据不存在 if (!$model) { return self::create($data + [ 'user_guid' => $guid, ]); } // token已过期 if ($model->is_exp) { $data['token_content'] = $model->generateContent($model); } $model->save($data); return $model; } /** * 登出 * * @date 2022-03-15 * @example * @author admin * @since 1.0.0 */ public static function logout(): void { self::getCurrent()->delete(); } /** * 获取请求token * * @date 2022-02-22 * @example * @author admin * @since 1.0.0 */ public static function getRequestToken(): string { $tokenKey = 'token'; $token = ''; if (!$token && isset($_GET[$tokenKey])) { $token = $_GET[$tokenKey]; } if (!$token && isset($_POST[$tokenKey])) { $token = $_POST[$tokenKey]; } if (!$token && Request::param($tokenKey)) { $token = Request::param($tokenKey); } if (!$token && Request::header($tokenKey)) { $token = Request::header($tokenKey); } return $token; } /** * 获取当前用户信息 * * @date 2022-02-22 * @example * @author admin * @since 1.0.0 */ public static function getCurrentUser(): User { if (!self::$user) { $model = self::getCurrent(); self::$user = $model->user; if (!self::$user) { throw new ErrorMsg("用户不存在", 1); } } return self::$user; } /** * 获取当前有效token * * @date 2022-02-28 * @example * @author admin * @since 1.0.0 */ public static function getCurrent(): self { if (!self::$current) { $content = self::getRequestToken(); if (!$content) { throw new LoginTimeOut("缺少token", 1); } $model = self::where([ 'token_content' => $content, ])->find(); if (!$model) { throw new LoginTimeOut("未登录", 1); } if ($model->is_exp) { throw new LoginTimeOut("登录超时", 1); } self::$current = $model; } return self::$current; } /** * 判断是否登录 * * @date 2022-05-14 * @example * @author admin * @since 1.0.0 */ public static function isLogin(): bool { try { self::getCurrent(); return true; } catch (LoginTimeOut $th) { return false; } } /** * 延长token * 过期前30分钟才会延期 * * @date 2022-02-28 * @example * @author admin * @since 1.0.0 */ public static function delay(): void { try { // 半小时 $delay = (60 * 30); $model = self::getCurrent(); $token_exp_time = $model->token_exp_timestamp; if (time() >= ($token_exp_time - $delay)) { self::login($model->user_guid); } } catch (LoginTimeOut $th) { } } /** * 生成token内容 * * @date 2022-02-22 * @example * @author admin * @since 1.0.0 */ private function generateContent(): string { return md5(join('-', [ $this->token_exp_time, $this->user_guid, ]) . time()); } }