Auth 登录鉴权

Auth 创建登录后将 Token 字符串存储在Cookie 中,通过主控制去引用该特性

  1. use app\system\controller\BaseController;
  2. use think\support\traits\Auth;
  3. class Main extends BaseController
  4. {
  5. use Auth;
  6. }

设置令牌自动刷新的总时效

  • refreshTokenExpires(): int
    • return int 默认 604800,单位< 秒 >
  1. use app\system\controller\BaseController;
  2. use think\support\traits\Auth;
  3. class Main extends BaseController
  4. {
  5. use Auth;
  6. protected function refreshTokenExpires()
  7. {
  8. return 7200;
  9. }
  10. }

创建登录鉴权

  • create(string $scene, array $symbol = []): array
    • scene string 场景标签
    • symbol array 标识
    • return array

在登录验证成功后调用

  1. use app\system\controller\BaseController;
  2. use think\support\traits\Auth;
  3. class Main extends BaseController
  4. {
  5. use Auth;
  6. public function login()
  7. {
  8. // $raws = ...
  9. // ...
  10. // 登录验证成功
  11. return $this->create('system', [
  12. 'user' => $raws['username'],
  13. 'role' => explode(',', $raws['role'])
  14. ]);
  15. }
  16. }

验证登录

  • authVerify(string $scene): array
    • scene string 场景标签
  1. use app\system\controller\BaseController;
  2. use think\support\traits\Auth;
  3. class Main extends BaseController
  4. {
  5. use Auth;
  6. public function verify()
  7. {
  8. return $this->authVerify('system');
  9. }
  10. }

验证返回钩子

  • authHook(array $symbol): array
    • symbol array 标识
  1. use app\system\controller\BaseController;
  2. use think\support\traits\Auth;
  3. class Main extends BaseController
  4. {
  5. use Auth;
  6. protected function authHook(array $symbol): array
  7. {
  8. $data = AdminRedis::create()->get($symbol['user']);
  9. if (empty($data)) {
  10. return [
  11. 'error' => 1,
  12. 'msg' => 'freeze'
  13. ];
  14. }
  15. return [
  16. 'error' => 0,
  17. 'msg' => 'ok'
  18. ];
  19. }
  20. }

销毁登录鉴权

  • destory(string $scene): array
    • scene string 场景标签
  1. use app\system\controller\BaseController;
  2. use think\support\traits\Auth;
  3. class Main extends BaseController
  4. {
  5. use Auth;
  6. public function logout()
  7. {
  8. return $this->destory('system');
  9. }
  10. }

RedisModel 缓存模型

使用 RedisModel 定义缓存模型,目的是将分散的缓存操作统一定义,例如:设定Acl访问控制表的缓存模型

  1. class Acl extends RedisModel
  2. {
  3. protected $key = 'system:acl';
  4. private $rows = [];
  5. /**
  6. * 清除缓存
  7. * @return bool
  8. */
  9. public function clear()
  10. {
  11. return (bool)$this->redis->del([$this->key]);
  12. }
  13. /**
  14. * @param string $key 访问控制键
  15. * @param int $policy 控制策略
  16. * @return array
  17. * @throws \Exception
  18. */
  19. public function get(string $key, int $policy)
  20. {
  21. if (!$this->redis->exists($this->key)) {
  22. $this->update($key);
  23. } else {
  24. $this->rows = json_decode($this->redis->hget($this->key, $key), true);
  25. }
  26. switch ($policy) {
  27. case 0:
  28. return explode(',', $this->rows['read']);
  29. case 1:
  30. return array_merge(
  31. explode(',', $this->rows['read']),
  32. explode(',', $this->rows['write'])
  33. );
  34. default:
  35. return [];
  36. }
  37. }
  38. /**
  39. * 更新缓存
  40. * @param string $key 访问控制键
  41. * @throws \Exception
  42. */
  43. private function update(string $key)
  44. {
  45. $lists = Db::name('acl')
  46. ->where('status', '=', 1)
  47. ->field(['key', 'write', 'read'])
  48. ->select();
  49. if (empty($lists)) {
  50. return;
  51. }
  52. $this->redis->pipeline(function (Pipeline $pipeline) use ($key, $lists) {
  53. foreach ($lists as $index => $value) {
  54. $pipeline->hset($this->key, $value['key'], json_encode([
  55. 'write' => $value['write'],
  56. 'read' => $value['read']
  57. ]));
  58. if ($key == $value['key']) {
  59. $this->rows = [
  60. 'write' => $value['write'],
  61. 'read' => $value['read']
  62. ];
  63. }
  64. }
  65. });
  66. }
  67. }

当对应的 acl 表数据发生变更时,执行 clear() 来清除缓存

  1. Acl::create()->clear();

通过缓存模型自定义的获取规则获取对应的数据,例如:查访问键 admin 对应的数据,如缓存不存在则生成缓存并返回数据

  1. Acl::create()->get('admin', 0);

如果同时要执行多个缓存模型,可以注入事务对象

  1. Redis::transaction(function (MultiExec $multiExec) {
  2. Someone1::create($multiExec)->factory();
  3. Someone2::create($multiExec)->factory();
  4. Someone3::create($multiExec)->factory();
  5. });

SMS 短信验证

手机短信验证码缓存类

设置手机验证码缓存

  • factory(string $phone, string $code, int $timeout = 120): string
    • phone string 手机号
    • code string 验证码
    • timeout int 超时时间,默认60秒
    • return bool
  1. Sms::create()->factory('12345678910', '13125');

验证手机验证码

  • check(string $phone, string $code, bool $once = false): bool
  • phone string 手机号
  • code string 验证码
  • once bool 验证成功后失效,默认false
  • return bool
  1. $sms = Sms::create();
  2. $checked = $sms->check('12345678910', '11224');
  3. dump($checked);
  4. // false
  5. $checked = $sms->check('12345678910', '13125');
  6. dump($checked);
  7. // true
  8. $checked = $sms->check('12345678910', '13125', true);
  9. dump($checked);
  10. // true
  11. $checked = $sms->check('12345678910', '13125');
  12. dump($checked);
  13. // false

获取验证时间

  • time(string $phone): array
    • phone string 手机号
    • return array
  1. $sms = Sms::create();
  2. $sms->factory('12345678910', '13125', 3600);
  3. $data = $sms->time('12345678910');
  4. dump($data);
  5. // array (size=2)
  6. // 'publish_time' => int 1548644216
  7. // 'timeout' => int 3600
  • publish_time int 指发布时间
  • timeout int 指有效时间

Refresh Token 缓存

Refresh Token 是用于自动刷新、验证对应 Token 的缓存模型

生产 Refresh Token

  • factory(string $jti, string $ack, int $expires): string
    • jti string JSON Web Token ID
    • ack string Token ID 验证码
    • expires int 存在时间,单位<秒>
    • return string
  1. $jti = Ext::uuid()->toString();
  2. $ack = Str::random();
  3. RefreshToken::create()->factory($jti, $ack, 86400*7);

验证 Token 的 Token ID 有效性

  • verify(string $jti, string $ack): bool
    • jti string JSON Web Token ID
    • ack string Token ID 验证码
    • return bool
  1. RefreshToken::create()->verify($jti, $ack);

清除 Token 对应的 Refresh Token

  • clear(string $jti, string $ack): bool
    • jti string JSON Web Token ID
    • ack string Token ID 验证码
    • return bool
  1. RefreshToken::create()->clear($jti, $ack);