123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- <?php
- // +----------------------------------------------------------------------
- // | ThinkAdmin
- // +----------------------------------------------------------------------
- // | 版权所有 2014~2020 广州楚才信息科技有限公司 [ http://www.cuci.cc ]
- // +----------------------------------------------------------------------
- // | 官方网站: https://gitee.com/zoujingli/ThinkLibrary
- // +----------------------------------------------------------------------
- // | 开源协议 ( https://mit-license.org )
- // +----------------------------------------------------------------------
- // | gitee 代码仓库:https://gitee.com/zoujingli/ThinkLibrary
- // | github 代码仓库:https://github.com/zoujingli/ThinkLibrary
- // +----------------------------------------------------------------------
- namespace think\admin\service;
- use think\admin\Service;
- /**
- * 表单令牌管理服务
- * Class TokenService
- * @package think\admin\service
- */
- class TokenService extends Service
- {
- /**
- * 令牌有效时间
- * @var integer
- */
- private $expire = 600;
- /**
- * 缓存分组名称
- * @var string
- */
- private $cachename;
- /**
- * 当前缓存数据
- * @var array
- */
- private $cachedata = [];
- /**
- * 表单令牌服务初始化
- */
- protected function initialize()
- {
- $user = AdminService::instance()->getUserName();
- $this->cachename = 'systoken_' . ($user ?: 'default');
- $this->cachedata = $this->_getCacheList(true);
- $this->app->event->listen('HttpEnd', function () {
- TokenService::instance()->saveCacheData();
- });
- }
- /**
- * 保存缓存到文件
- */
- public function saveCacheData()
- {
- $this->_clearTimeoutCache();
- $this->app->cache->set($this->cachename, $this->cachedata, $this->expire);
- }
- /**
- * 获取当前请求 CSRF 值
- * @return array|string
- */
- public function getInputToken()
- {
- return $this->app->request->header('user-form-token', input('_csrf_', ''));
- }
- /**
- * 验证 CSRF 是否有效
- * @param string $token 表单令牌
- * @param string $node 授权节点
- * @return boolean
- */
- public function checkFormToken($token = null, $node = null)
- {
- $cnode = NodeService::instance()->fullnode($node);
- $cache = $this->_getCacheItem($token ?: $this->getInputToken());
- if (empty($cache['node']) || empty($cache['time'])) return false;
- if (strtolower($cache['node']) !== strtolower($cnode)) return false;
- return true;
- }
- /**
- * 清理表单 CSRF 数据
- * @param string $token
- * @return $this
- */
- public function clearFormToken($token = null)
- {
- $this->_delCacheItem($token ?: $this->getInputToken());
- return $this;
- }
- /**
- * 生成表单 CSRF 数据
- * @param string $node
- * @return array
- */
- public function buildFormToken($node = null)
- {
- $cnode = NodeService::instance()->fullnode($node);
- [$token, $time] = [uniqid() . rand(100000, 999999), time()];
- $this->_setCacheItem($token, $item = ['node' => $cnode, 'time' => $time]);
- return array_merge($item, ['token' => $token]);
- }
- /**
- * 清空所有 CSRF 数据
- */
- public function clearCache()
- {
- $this->app->cache->delete($this->cachename);
- }
- /**
- * 设置缓存数据
- * @param string $token
- * @param array $item
- * @return static
- */
- private function _setCacheItem(string $token, array $item)
- {
- $this->cachedata[$token] = $item;
- return $this;
- }
- /**
- * 删除缓存
- * @param string $token
- */
- private function _delCacheItem(string $token)
- {
- unset($this->cachedata[$token]);
- }
- /**
- * 获取指定缓存
- * @param string $token
- * @param array $default
- * @return mixed
- */
- private function _getCacheItem(string $token, $default = [])
- {
- $this->_clearTimeoutCache();
- return $this->cachedata[$token] ?? $default;
- }
- /**
- * 获取缓存列表
- * @param bool $clear 强制清理
- * @return array
- */
- private function _getCacheList(bool $clear = false): array
- {
- $this->cachedata = $this->app->cache->get($this->cachename, []);
- if ($clear) $this->cachedata = $this->_clearTimeoutCache();
- return $this->cachedata;
- }
- /**
- * 清理超时的缓存
- * @return array
- */
- private function _clearTimeoutCache(): array
- {
- $time = time();
- foreach ($this->cachedata as $key => $item) {
- if (empty($item['time']) || $item['time'] + $this->expire < $time) {
- unset($this->cachedata[$key]);
- }
- }
- if (count($this->cachedata) > 99) {
- $this->cachedata = array_slice($this->cachedata, -99);
- }
- return $this->cachedata;
- }
- }
|