diff --git a/application/common/library/token/Driver.php b/application/common/library/token/Driver.php new file mode 100644 index 0000000..7e2dfa7 --- /dev/null +++ b/application/common/library/token/Driver.php @@ -0,0 +1,91 @@ +<?php +// +---------------------------------------------------------------------- +// | ThinkPHP [ WE CAN DO IT JUST THINK ] +// +---------------------------------------------------------------------- +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved. +// +---------------------------------------------------------------------- +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) +// +---------------------------------------------------------------------- +// | Author: liu21st <liu21st@gmail.com> +// +---------------------------------------------------------------------- + +namespace app\common\library\token; + +/** + * Token基础类 + */ +abstract class Driver +{ + protected $handler = null; + protected $options = []; + + /** + * 存储Token + * @param string $token Token + * @param int $user_id 会员ID + * @param int $expire 过期时长,0表示无限,单位秒 + * @return bool + */ + abstract function set($token, $user_id, $expire = 0); + + /** + * 获取Token内的信息 + * @param string $token + * @return array + */ + abstract function get($token); + + /** + * 判断Token是否可用 + * @param string $token Token + * @param int $user_id 会员ID + * @return boolean + */ + abstract function check($token, $user_id); + + /** + * 删除Token + * @param string $token + * @return boolean + */ + abstract function delete($token); + + /** + * 删除指定用户的所有Token + * @param int $user_id + * @return boolean + */ + abstract function clear($user_id); + + /** + * 返回句柄对象,可执行其它高级方法 + * + * @access public + * @return object + */ + public function handler() + { + return $this->handler; + } + + /** + * 获取加密后的Token + * @param string $token Token标识 + * @return string + */ + protected function getEncryptedToken($token) + { + $config = \think\Config::get('token'); + return hash_hmac($config['hashalgo'], $token, $config['key']); + } + + /** + * 获取过期剩余时长 + * @param $expiretime + * @return float|int|mixed + */ + protected function getExpiredIn($expiretime) + { + return $expiretime ? max(0, $expiretime - time()) : 365 * 86400; + } +} diff --git a/application/common/library/token/driver/Mysql.php b/application/common/library/token/driver/Mysql.php new file mode 100644 index 0000000..c61fcd6 --- /dev/null +++ b/application/common/library/token/driver/Mysql.php @@ -0,0 +1,112 @@ +<?php + +namespace app\common\library\token\driver; + +use app\common\library\token\Driver; + +/** + * Token操作类 + */ +class Mysql extends Driver +{ + + /** + * 默认配置 + * @var array + */ + protected $options = [ + 'table' => 'user_token', + 'expire' => 2592000, + 'connection' => [], + ]; + + + /** + * 构造函数 + * @param array $options 参数 + * @access public + */ + public function __construct($options = []) + { + if (!empty($options)) { + $this->options = array_merge($this->options, $options); + } + if ($this->options['connection']) { + $this->handler = \think\Db::connect($this->options['connection'])->name($this->options['table']); + } else { + $this->handler = \think\Db::name('user_token'); + } + } + + /** + * 存储Token + * @param string $token Token + * @param int $user_id 会员ID + * @param int $expire 过期时长,0表示无限,单位秒 + * @return bool + */ + public function set($token, $user_id, $expire = null) + { + $expiretime = !is_null($expire) ? time() + $expire : ($expire === 0 ? 0 : time() + $this->options['expire']); + $token = $this->getEncryptedToken($token); + $this->handler->insert(['token' => $token, 'user_id' => $user_id, 'createtime' => time(), 'expiretime' => $expiretime]); + return TRUE; + } + + /** + * 获取Token内的信息 + * @param string $token + * @return array + */ + public function get($token) + { + $data = $this->handler->where('token', $this->getEncryptedToken($token))->find(); + if ($data) { + if (!$data['expiretime'] || $data['expiretime'] > time()) { + //返回未加密的token给客户端使用 + $data['token'] = $token; + //返回剩余有效时间 + $data['expired_in'] = $this->getExpiredIn($data['expiretime']); + return $data; + } else { + self::delete($token); + } + } + return []; + } + + /** + * 判断Token是否可用 + * @param string $token Token + * @param int $user_id 会员ID + * @return boolean + */ + public function check($token, $user_id) + { + $data = $this->get($token); + return $data && $data['user_id'] == $user_id ? true : false; + } + + /** + * 删除Token + * @param string $token + * @return boolean + */ + public function delete($token) + { + $this->handler->where('token', $this->getEncryptedToken($token))->delete(); + return true; + } + + /** + * 删除指定用户的所有Token + * @param int $user_id + * @return boolean + */ + public function clear($user_id) + { + $this->handler->where('user_id', $user_id)->delete(); + return true; + } + +} diff --git a/application/common/library/token/driver/Redis.php b/application/common/library/token/driver/Redis.php new file mode 100644 index 0000000..877da4c --- /dev/null +++ b/application/common/library/token/driver/Redis.php @@ -0,0 +1,166 @@ +<?php + +namespace app\common\library\token\driver; + +use app\common\library\token\Driver; + +/** + * Token操作类 + */ +class Redis extends Driver +{ + + protected $options = [ + 'host' => '127.0.0.1', + 'port' => 6379, + 'password' => '', + 'select' => 0, + 'timeout' => 0, + 'expire' => 0, + 'persistent' => false, + 'userprefix' => 'up:', + 'tokenprefix' => 'tp:', + ]; + + /** + * 构造函数 + * @param array $options 缓存参数 + * @throws \BadFunctionCallException + * @access public + */ + public function __construct($options = []) + { + if (!extension_loaded('redis')) { + throw new \BadFunctionCallException('not support: redis'); + } + if (!empty($options)) { + $this->options = array_merge($this->options, $options); + } + $this->handler = new \Redis; + if ($this->options['persistent']) { + $this->handler->pconnect($this->options['host'], $this->options['port'], $this->options['timeout'], 'persistent_id_' . $this->options['select']); + } else { + $this->handler->connect($this->options['host'], $this->options['port'], $this->options['timeout']); + } + + if ('' != $this->options['password']) { + $this->handler->auth($this->options['password']); + } + + if (0 != $this->options['select']) { + $this->handler->select($this->options['select']); + } + } + + /** + * 获取加密后的Token + * @param string $token Token标识 + * @return string + */ + protected function getEncryptedToken($token) + { + $config = \think\Config::get('token'); + return $this->options['tokenprefix'] . hash_hmac($config['hashalgo'], $token, $config['key']); + } + + /** + * 获取会员的key + * @param $user_id + * @return string + */ + protected function getUserKey($user_id) + { + return $this->options['userprefix'] . $user_id; + } + + /** + * 存储Token + * @param string $token Token + * @param int $user_id 会员ID + * @param int $expire 过期时长,0表示无限,单位秒 + * @return bool + */ + public function set($token, $user_id, $expire = 0) + { + if (is_null($expire)) { + $expire = $this->options['expire']; + } + if ($expire instanceof \DateTime) { + $expire = $expire->getTimestamp() - time(); + } + $key = $this->getEncryptedToken($token); + if ($expire) { + $result = $this->handler->setex($key, $expire, $user_id); + } else { + $result = $this->handler->set($key, $user_id); + } + //写入会员关联的token + $this->handler->sAdd($this->getUserKey($user_id), $key); + return $result; + } + + /** + * 获取Token内的信息 + * @param string $token + * @return array + */ + public function get($token) + { + $key = $this->getEncryptedToken($token); + $value = $this->handler->get($key); + if (is_null($value) || false === $value) { + return []; + } + //获取有效期 + $expire = $this->handler->ttl($key); + $expire = $expire < 0 ? 365 * 86400 : $expire; + $expiretime = time() + $expire; + $result = ['token' => $token, 'user_id' => $value, 'expiretime' => $expiretime, 'expired_in' => $expire]; + + return $result; + } + + /** + * 判断Token是否可用 + * @param string $token Token + * @param int $user_id 会员ID + * @return boolean + */ + public function check($token, $user_id) + { + $data = self::get($token); + return $data && $data['user_id'] == $user_id ? true : false; + } + + /** + * 删除Token + * @param string $token + * @return boolean + */ + public function delete($token) + { + $data = $this->get($token); + if ($data) { + $key = $this->getEncryptedToken($token); + $user_id = $data['user_id']; + $this->handler->del($key); + $this->handler->sRem($this->getUserKey($user_id), $key); + } + return true; + + } + + /** + * 删除指定用户的所有Token + * @param int $user_id + * @return boolean + */ + public function clear($user_id) + { + $keys = $this->handler->sMembers($this->getUserKey($user_id)); + $this->handler->del($this->getUserKey($user_id)); + $this->handler->del($keys); + return true; + } + +}