作者 Karson

新增Token的Redis和Mysql驱动方式

  1 +<?php
  2 +// +----------------------------------------------------------------------
  3 +// | ThinkPHP [ WE CAN DO IT JUST THINK ]
  4 +// +----------------------------------------------------------------------
  5 +// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
  6 +// +----------------------------------------------------------------------
  7 +// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
  8 +// +----------------------------------------------------------------------
  9 +// | Author: liu21st <liu21st@gmail.com>
  10 +// +----------------------------------------------------------------------
  11 +
  12 +namespace app\common\library\token;
  13 +
  14 +/**
  15 + * Token基础类
  16 + */
  17 +abstract class Driver
  18 +{
  19 + protected $handler = null;
  20 + protected $options = [];
  21 +
  22 + /**
  23 + * 存储Token
  24 + * @param string $token Token
  25 + * @param int $user_id 会员ID
  26 + * @param int $expire 过期时长,0表示无限,单位秒
  27 + * @return bool
  28 + */
  29 + abstract function set($token, $user_id, $expire = 0);
  30 +
  31 + /**
  32 + * 获取Token内的信息
  33 + * @param string $token
  34 + * @return array
  35 + */
  36 + abstract function get($token);
  37 +
  38 + /**
  39 + * 判断Token是否可用
  40 + * @param string $token Token
  41 + * @param int $user_id 会员ID
  42 + * @return boolean
  43 + */
  44 + abstract function check($token, $user_id);
  45 +
  46 + /**
  47 + * 删除Token
  48 + * @param string $token
  49 + * @return boolean
  50 + */
  51 + abstract function delete($token);
  52 +
  53 + /**
  54 + * 删除指定用户的所有Token
  55 + * @param int $user_id
  56 + * @return boolean
  57 + */
  58 + abstract function clear($user_id);
  59 +
  60 + /**
  61 + * 返回句柄对象,可执行其它高级方法
  62 + *
  63 + * @access public
  64 + * @return object
  65 + */
  66 + public function handler()
  67 + {
  68 + return $this->handler;
  69 + }
  70 +
  71 + /**
  72 + * 获取加密后的Token
  73 + * @param string $token Token标识
  74 + * @return string
  75 + */
  76 + protected function getEncryptedToken($token)
  77 + {
  78 + $config = \think\Config::get('token');
  79 + return hash_hmac($config['hashalgo'], $token, $config['key']);
  80 + }
  81 +
  82 + /**
  83 + * 获取过期剩余时长
  84 + * @param $expiretime
  85 + * @return float|int|mixed
  86 + */
  87 + protected function getExpiredIn($expiretime)
  88 + {
  89 + return $expiretime ? max(0, $expiretime - time()) : 365 * 86400;
  90 + }
  91 +}
  1 +<?php
  2 +
  3 +namespace app\common\library\token\driver;
  4 +
  5 +use app\common\library\token\Driver;
  6 +
  7 +/**
  8 + * Token操作类
  9 + */
  10 +class Mysql extends Driver
  11 +{
  12 +
  13 + /**
  14 + * 默认配置
  15 + * @var array
  16 + */
  17 + protected $options = [
  18 + 'table' => 'user_token',
  19 + 'expire' => 2592000,
  20 + 'connection' => [],
  21 + ];
  22 +
  23 +
  24 + /**
  25 + * 构造函数
  26 + * @param array $options 参数
  27 + * @access public
  28 + */
  29 + public function __construct($options = [])
  30 + {
  31 + if (!empty($options)) {
  32 + $this->options = array_merge($this->options, $options);
  33 + }
  34 + if ($this->options['connection']) {
  35 + $this->handler = \think\Db::connect($this->options['connection'])->name($this->options['table']);
  36 + } else {
  37 + $this->handler = \think\Db::name('user_token');
  38 + }
  39 + }
  40 +
  41 + /**
  42 + * 存储Token
  43 + * @param string $token Token
  44 + * @param int $user_id 会员ID
  45 + * @param int $expire 过期时长,0表示无限,单位秒
  46 + * @return bool
  47 + */
  48 + public function set($token, $user_id, $expire = null)
  49 + {
  50 + $expiretime = !is_null($expire) ? time() + $expire : ($expire === 0 ? 0 : time() + $this->options['expire']);
  51 + $token = $this->getEncryptedToken($token);
  52 + $this->handler->insert(['token' => $token, 'user_id' => $user_id, 'createtime' => time(), 'expiretime' => $expiretime]);
  53 + return TRUE;
  54 + }
  55 +
  56 + /**
  57 + * 获取Token内的信息
  58 + * @param string $token
  59 + * @return array
  60 + */
  61 + public function get($token)
  62 + {
  63 + $data = $this->handler->where('token', $this->getEncryptedToken($token))->find();
  64 + if ($data) {
  65 + if (!$data['expiretime'] || $data['expiretime'] > time()) {
  66 + //返回未加密的token给客户端使用
  67 + $data['token'] = $token;
  68 + //返回剩余有效时间
  69 + $data['expired_in'] = $this->getExpiredIn($data['expiretime']);
  70 + return $data;
  71 + } else {
  72 + self::delete($token);
  73 + }
  74 + }
  75 + return [];
  76 + }
  77 +
  78 + /**
  79 + * 判断Token是否可用
  80 + * @param string $token Token
  81 + * @param int $user_id 会员ID
  82 + * @return boolean
  83 + */
  84 + public function check($token, $user_id)
  85 + {
  86 + $data = $this->get($token);
  87 + return $data && $data['user_id'] == $user_id ? true : false;
  88 + }
  89 +
  90 + /**
  91 + * 删除Token
  92 + * @param string $token
  93 + * @return boolean
  94 + */
  95 + public function delete($token)
  96 + {
  97 + $this->handler->where('token', $this->getEncryptedToken($token))->delete();
  98 + return true;
  99 + }
  100 +
  101 + /**
  102 + * 删除指定用户的所有Token
  103 + * @param int $user_id
  104 + * @return boolean
  105 + */
  106 + public function clear($user_id)
  107 + {
  108 + $this->handler->where('user_id', $user_id)->delete();
  109 + return true;
  110 + }
  111 +
  112 +}
  1 +<?php
  2 +
  3 +namespace app\common\library\token\driver;
  4 +
  5 +use app\common\library\token\Driver;
  6 +
  7 +/**
  8 + * Token操作类
  9 + */
  10 +class Redis extends Driver
  11 +{
  12 +
  13 + protected $options = [
  14 + 'host' => '127.0.0.1',
  15 + 'port' => 6379,
  16 + 'password' => '',
  17 + 'select' => 0,
  18 + 'timeout' => 0,
  19 + 'expire' => 0,
  20 + 'persistent' => false,
  21 + 'userprefix' => 'up:',
  22 + 'tokenprefix' => 'tp:',
  23 + ];
  24 +
  25 + /**
  26 + * 构造函数
  27 + * @param array $options 缓存参数
  28 + * @throws \BadFunctionCallException
  29 + * @access public
  30 + */
  31 + public function __construct($options = [])
  32 + {
  33 + if (!extension_loaded('redis')) {
  34 + throw new \BadFunctionCallException('not support: redis');
  35 + }
  36 + if (!empty($options)) {
  37 + $this->options = array_merge($this->options, $options);
  38 + }
  39 + $this->handler = new \Redis;
  40 + if ($this->options['persistent']) {
  41 + $this->handler->pconnect($this->options['host'], $this->options['port'], $this->options['timeout'], 'persistent_id_' . $this->options['select']);
  42 + } else {
  43 + $this->handler->connect($this->options['host'], $this->options['port'], $this->options['timeout']);
  44 + }
  45 +
  46 + if ('' != $this->options['password']) {
  47 + $this->handler->auth($this->options['password']);
  48 + }
  49 +
  50 + if (0 != $this->options['select']) {
  51 + $this->handler->select($this->options['select']);
  52 + }
  53 + }
  54 +
  55 + /**
  56 + * 获取加密后的Token
  57 + * @param string $token Token标识
  58 + * @return string
  59 + */
  60 + protected function getEncryptedToken($token)
  61 + {
  62 + $config = \think\Config::get('token');
  63 + return $this->options['tokenprefix'] . hash_hmac($config['hashalgo'], $token, $config['key']);
  64 + }
  65 +
  66 + /**
  67 + * 获取会员的key
  68 + * @param $user_id
  69 + * @return string
  70 + */
  71 + protected function getUserKey($user_id)
  72 + {
  73 + return $this->options['userprefix'] . $user_id;
  74 + }
  75 +
  76 + /**
  77 + * 存储Token
  78 + * @param string $token Token
  79 + * @param int $user_id 会员ID
  80 + * @param int $expire 过期时长,0表示无限,单位秒
  81 + * @return bool
  82 + */
  83 + public function set($token, $user_id, $expire = 0)
  84 + {
  85 + if (is_null($expire)) {
  86 + $expire = $this->options['expire'];
  87 + }
  88 + if ($expire instanceof \DateTime) {
  89 + $expire = $expire->getTimestamp() - time();
  90 + }
  91 + $key = $this->getEncryptedToken($token);
  92 + if ($expire) {
  93 + $result = $this->handler->setex($key, $expire, $user_id);
  94 + } else {
  95 + $result = $this->handler->set($key, $user_id);
  96 + }
  97 + //写入会员关联的token
  98 + $this->handler->sAdd($this->getUserKey($user_id), $key);
  99 + return $result;
  100 + }
  101 +
  102 + /**
  103 + * 获取Token内的信息
  104 + * @param string $token
  105 + * @return array
  106 + */
  107 + public function get($token)
  108 + {
  109 + $key = $this->getEncryptedToken($token);
  110 + $value = $this->handler->get($key);
  111 + if (is_null($value) || false === $value) {
  112 + return [];
  113 + }
  114 + //获取有效期
  115 + $expire = $this->handler->ttl($key);
  116 + $expire = $expire < 0 ? 365 * 86400 : $expire;
  117 + $expiretime = time() + $expire;
  118 + $result = ['token' => $token, 'user_id' => $value, 'expiretime' => $expiretime, 'expired_in' => $expire];
  119 +
  120 + return $result;
  121 + }
  122 +
  123 + /**
  124 + * 判断Token是否可用
  125 + * @param string $token Token
  126 + * @param int $user_id 会员ID
  127 + * @return boolean
  128 + */
  129 + public function check($token, $user_id)
  130 + {
  131 + $data = self::get($token);
  132 + return $data && $data['user_id'] == $user_id ? true : false;
  133 + }
  134 +
  135 + /**
  136 + * 删除Token
  137 + * @param string $token
  138 + * @return boolean
  139 + */
  140 + public function delete($token)
  141 + {
  142 + $data = $this->get($token);
  143 + if ($data) {
  144 + $key = $this->getEncryptedToken($token);
  145 + $user_id = $data['user_id'];
  146 + $this->handler->del($key);
  147 + $this->handler->sRem($this->getUserKey($user_id), $key);
  148 + }
  149 + return true;
  150 +
  151 + }
  152 +
  153 + /**
  154 + * 删除指定用户的所有Token
  155 + * @param int $user_id
  156 + * @return boolean
  157 + */
  158 + public function clear($user_id)
  159 + {
  160 + $keys = $this->handler->sMembers($this->getUserKey($user_id));
  161 + $this->handler->del($this->getUserKey($user_id));
  162 + $this->handler->del($keys);
  163 + return true;
  164 + }
  165 +
  166 +}