feat: jwt
This commit is contained in:
16
app/Cache/Redis/Admin/AdminRedisKey.php
Normal file
16
app/Cache/Redis/Admin/AdminRedisKey.php
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Cache\Redis\Admin;
|
||||||
|
|
||||||
|
class AdminRedisKey
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 用户token
|
||||||
|
* @param $userId
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public static function adminUserToken($userId): string
|
||||||
|
{
|
||||||
|
return 'admin:token:user:'.$userId;
|
||||||
|
}
|
||||||
|
}
|
||||||
47
app/Cache/Redis/Admin/UserCache.php
Normal file
47
app/Cache/Redis/Admin/UserCache.php
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Cache\Redis\Admin;
|
||||||
|
|
||||||
|
use App\Cache\Redis\RedisCache;
|
||||||
|
use Hyperf\Di\Annotation\Inject;
|
||||||
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
|
|
||||||
|
class UserCache
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var RedisCache $redis
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected RedisCache $redis;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $userId
|
||||||
|
* @return string|false
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws \RedisException
|
||||||
|
*/
|
||||||
|
public function getAdminToken($userId): false|string
|
||||||
|
{
|
||||||
|
return $this->redis->get(AdminRedisKey::adminUserToken($userId),'system') ?? false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $userId
|
||||||
|
* @param string $token
|
||||||
|
* @param int $ttl
|
||||||
|
* @return bool
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws \RedisException
|
||||||
|
*/
|
||||||
|
public function setAdminToken($userId, string $token, int $ttl): bool
|
||||||
|
{
|
||||||
|
$key = AdminRedisKey::adminUserToken($userId);
|
||||||
|
$this->redis->delete($key,'system');
|
||||||
|
return $this->redis->setEx($key, $token, $ttl, 'system');
|
||||||
|
}
|
||||||
|
}
|
||||||
493
app/Cache/Redis/RedisCache.php
Normal file
493
app/Cache/Redis/RedisCache.php
Normal file
@@ -0,0 +1,493 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Cache\Redis;
|
||||||
|
|
||||||
|
use Hyperf\Context\ApplicationContext;
|
||||||
|
use Hyperf\Redis\RedisFactory;
|
||||||
|
use Hyperf\Redis\RedisProxy;
|
||||||
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
|
use Redis;
|
||||||
|
use RedisException;
|
||||||
|
|
||||||
|
class RedisCache
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* 获取 redis 对象
|
||||||
|
* @param string $poolName
|
||||||
|
* @return RedisProxy
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
private function getRedis(string $poolName = 'default'): RedisProxy
|
||||||
|
{
|
||||||
|
return ApplicationContext::getContainer()->get(RedisFactory::class)->get($poolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
// | atom 原子操作
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* @param string $script
|
||||||
|
* @param array $array
|
||||||
|
* @param int $num
|
||||||
|
* @param string $poolName
|
||||||
|
* @return mixed
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function eval(string $script, array $array, int $num = 1, string $poolName = 'default'): mixed
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->eval($script, $array, $num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key
|
||||||
|
* @param int $ttl
|
||||||
|
* @param string $poolName
|
||||||
|
* @return int
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function addLock(string $key, int $ttl = 5, string $poolName = 'lock'): int
|
||||||
|
{
|
||||||
|
$script = <<<lua
|
||||||
|
local isLock = redis.call('exists',KEYS[1])
|
||||||
|
if isLock == 1 then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
redis.call('set',KEYS[1],1)
|
||||||
|
redis.call('Expire',KEYS[1],ARGV[1])
|
||||||
|
return 1;
|
||||||
|
end
|
||||||
|
lua;
|
||||||
|
|
||||||
|
return $this->getRedis($poolName)->eval($script, [$key, $ttl], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key
|
||||||
|
* @param string $poolName
|
||||||
|
* @return int|bool
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface|RedisException
|
||||||
|
*/
|
||||||
|
public function delLock(string $key, string $poolName = 'lock'): int|bool
|
||||||
|
{
|
||||||
|
return $this->delete($key, $poolName);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
// | key
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* 判断 key 是否存在
|
||||||
|
* @param string $key
|
||||||
|
* @param string $poolName
|
||||||
|
* @return int|bool
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function exists(string $key, string $poolName = 'default'): int|bool
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->exists($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除
|
||||||
|
* @param string $key
|
||||||
|
* @param string $poolName
|
||||||
|
* @return int|bool
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function delete(string $key, string $poolName = 'default'): int|bool
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->del($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key
|
||||||
|
* @param int $ex
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function expire(string $key, int $ex, string $poolName = 'default'): bool
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->expire($key, $ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回过期时间 -1=key存在未设置过期时间 -2=key不存在 >0 = 过期时间(秒)
|
||||||
|
* @param string $key
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool|int|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function ttl(string $key, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->ttl($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
// | string
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* 设置一个key
|
||||||
|
* @param string $key
|
||||||
|
* @param string $value
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function set(string $key, string $value, string $poolName = 'default'): bool
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->set($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取key
|
||||||
|
* @param string $key
|
||||||
|
* @param string $poolName
|
||||||
|
* @return false|mixed|Redis|string
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function get(string $key, string $poolName = 'default'): mixed
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->get($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加一个有过期值的key (ps:如果 key 已经存在, setEx 命令将会替换旧的值。)
|
||||||
|
* @param string $key
|
||||||
|
* @param string $value
|
||||||
|
* @param int $ttl
|
||||||
|
* @param string $poolName
|
||||||
|
* @return Redis|bool
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function setEx(string $key, string $value, int $ttl, string $poolName = 'default'): Redis|bool
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->setex($key, $ttl, $value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 key 中储存的数字值增一。
|
||||||
|
* 如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执行 INCR 操作。
|
||||||
|
* @param $key
|
||||||
|
* @param string $poolName
|
||||||
|
* @return false|int|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function incr($key, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->incr($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
// | set
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* 判断 value 元素是否是集合 key 的成员
|
||||||
|
* 如果 member 元素是集合的成员,返回 1 。
|
||||||
|
* 如果 member 元素不是集合的成员,或 key 不存在,返回 0 。
|
||||||
|
* @param $key
|
||||||
|
* @param $value
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function sIsMember($key, $value, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->sIsMember($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加集合成员
|
||||||
|
* @param $key
|
||||||
|
* @param $value
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool|int|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
public function sAdd($key, $value, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->sAdd($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取集合所有内容
|
||||||
|
* @param $key
|
||||||
|
* @param string $poolName
|
||||||
|
* @return array|false|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function sMembers($key, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->sMembers($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除集合成员
|
||||||
|
* @param $key
|
||||||
|
* @param $value
|
||||||
|
* @param string $poolName
|
||||||
|
* @return false|int|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
public function sRem($key, $value, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->sRem($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
// | hash
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* 设置多个key-value 的 hash值
|
||||||
|
* @param $key
|
||||||
|
* @param $hashKeys
|
||||||
|
* @param null $expire
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function hMset($key, $hashKeys, $expire = null, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
$result = $this->getRedis($poolName)->hMset($key, $hashKeys);
|
||||||
|
if ($expire) {
|
||||||
|
$this->getRedis($poolName)->expire($key, $expire);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回列表 key 的集合数据
|
||||||
|
* @param $key
|
||||||
|
* @param string $poolName
|
||||||
|
* @return false|array|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function hGetAll($key, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->hGetAll($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置单个key-value 的 hash值
|
||||||
|
* @param $key
|
||||||
|
* @param $hashKey
|
||||||
|
* @param $hashValue
|
||||||
|
* @param int $expire
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool|int|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function hSet($key, $hashKey, $hashValue, int $expire = 0, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
$result = $this->getRedis($poolName)->hSet($key, $hashKey, $hashValue);
|
||||||
|
if ($expire) {
|
||||||
|
$this->getRedis($poolName)->expire($key, $expire);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取单个字段的 hash 值
|
||||||
|
* @param $key
|
||||||
|
* @param $hashKey
|
||||||
|
* @param string $poolName
|
||||||
|
* @return false|mixed|Redis|string
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function hGet($key, $hashKey, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->hGet($key, $hashKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除hash某个值
|
||||||
|
* @param $key
|
||||||
|
* @param $hashKey
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool|int|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function hDel($key, $hashKey, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->hDel($key, $hashKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找hash某个值
|
||||||
|
* @param $key
|
||||||
|
* @param $hashKey
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function hExists($key, $hashKey, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->hExists($key, $hashKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 单个字段的 hash 值原子增加
|
||||||
|
* @param $key
|
||||||
|
* @param $hashKey
|
||||||
|
* @param $hashValue
|
||||||
|
* @param string $poolName
|
||||||
|
* @return false|int|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function HIncrBy($key, $hashKey, $hashValue, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->hincrby($key, $hashKey, $hashValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
// | list
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* 从左边入
|
||||||
|
* @param string $key
|
||||||
|
* @param string $data
|
||||||
|
* @param string $poolName
|
||||||
|
* @return false|int|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function lPush(string $key, string $data, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->lPush($key, $data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从右边出
|
||||||
|
* @param $key
|
||||||
|
* @param string $poolName
|
||||||
|
* @return array|bool|mixed|Redis|string
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function rPop($key, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->rPop($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量加入数据
|
||||||
|
* @param $data
|
||||||
|
* @param string $poolName
|
||||||
|
* @return RedisProxy
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
*/
|
||||||
|
public function lPushBatch($data, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
$result = $this->getRedis($poolName);
|
||||||
|
call_user_func_array([$result, 'lPush'], $data);
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 返回列表 key 的长度
|
||||||
|
* @param $key
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool|int|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function lLen($key, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->lLen($key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
// | sorted set
|
||||||
|
// +--------------------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
/**
|
||||||
|
* 返回有序集 key 中,成员 member 的 score 值。
|
||||||
|
* 如果 member 元素不是有序集 key 的成员,或 key 不存在,返回 nil 。
|
||||||
|
* @param $key
|
||||||
|
* @param $value
|
||||||
|
* @param string $poolName
|
||||||
|
* @return bool|float|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function zScore($key, $value, string $poolName = 'default')
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->zScore($key, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加入有序集合
|
||||||
|
* @param $key
|
||||||
|
* @param $score
|
||||||
|
* @param string $poolName
|
||||||
|
* @param ...$value
|
||||||
|
* @return false|int|Redis
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
|
public function zAdd($key, $score, string $poolName = 'default', ...$value)
|
||||||
|
{
|
||||||
|
return $this->getRedis($poolName)->zAdd($key, $score, ...$value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -11,4 +11,9 @@ class AdminCode extends ReturnCode
|
|||||||
* @Message("登录失败")
|
* @Message("登录失败")
|
||||||
*/
|
*/
|
||||||
public const int LOGIN_ERROR = 10001;
|
public const int LOGIN_ERROR = 10001;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Message("登录token已失效")
|
||||||
|
*/
|
||||||
|
public const int LOGIN_TOKEN_ERROR = 10002;
|
||||||
}
|
}
|
||||||
@@ -5,16 +5,19 @@ declare(strict_types=1);
|
|||||||
namespace App\Controller\Admin;
|
namespace App\Controller\Admin;
|
||||||
|
|
||||||
use App\Controller\AbstractController;
|
use App\Controller\AbstractController;
|
||||||
|
use App\Middleware\Admin\JwtAuthMiddleware;
|
||||||
use App\Request\Admin\AuthRequest;
|
use App\Request\Admin\AuthRequest;
|
||||||
use App\Service\Admin\User\RoleMenuService;
|
use App\Service\Admin\User\RoleMenuService;
|
||||||
use App\Service\Admin\User\RoleService;
|
use App\Service\Admin\User\RoleService;
|
||||||
use Hyperf\HttpServer\Annotation\Controller;
|
use Hyperf\HttpServer\Annotation\Controller;
|
||||||
|
use Hyperf\HttpServer\Annotation\Middlewares;
|
||||||
use Hyperf\HttpServer\Annotation\RequestMapping;
|
use Hyperf\HttpServer\Annotation\RequestMapping;
|
||||||
use Hyperf\HttpServer\Contract\RequestInterface;
|
|
||||||
use Hyperf\HttpServer\Contract\ResponseInterface;
|
|
||||||
use Hyperf\Validation\Annotation\Scene;
|
use Hyperf\Validation\Annotation\Scene;
|
||||||
|
|
||||||
#[Controller(prefix: "admin/auth")]
|
#[Controller(prefix: "admin/auth")]
|
||||||
|
#[Middlewares([
|
||||||
|
JwtAuthMiddleware::class,
|
||||||
|
])]
|
||||||
class AuthController extends AbstractController
|
class AuthController extends AbstractController
|
||||||
{
|
{
|
||||||
public function menu_add(AuthRequest $request)
|
public function menu_add(AuthRequest $request)
|
||||||
|
|||||||
@@ -10,13 +10,24 @@ use App\Service\Admin\User\LoginService;
|
|||||||
use Hyperf\HttpServer\Annotation\Controller;
|
use Hyperf\HttpServer\Annotation\Controller;
|
||||||
use Hyperf\HttpServer\Annotation\RequestMapping;
|
use Hyperf\HttpServer\Annotation\RequestMapping;
|
||||||
use Hyperf\Validation\Annotation\Scene;
|
use Hyperf\Validation\Annotation\Scene;
|
||||||
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
|
use RedisException;
|
||||||
|
|
||||||
#[Controller(prefix: "admin/login")]
|
#[Controller(prefix: "admin/login")]
|
||||||
class LoginController extends AbstractController
|
class LoginController extends AbstractController
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* 登录
|
||||||
|
* @param LoginRequest $request
|
||||||
|
* @return array
|
||||||
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws RedisException
|
||||||
|
*/
|
||||||
#[RequestMapping(path: "user", methods: "POST")]
|
#[RequestMapping(path: "user", methods: "POST")]
|
||||||
#[Scene(scene: "login")]
|
#[Scene(scene: "login")]
|
||||||
public function login(LoginRequest $request)
|
public function login(LoginRequest $request): array
|
||||||
{
|
{
|
||||||
$service = new LoginService();
|
$service = new LoginService();
|
||||||
return $service->handle();
|
return $service->handle();
|
||||||
|
|||||||
@@ -42,6 +42,11 @@ class CryptoFactory
|
|||||||
$jwtCrypto = new JwtCrypto();
|
$jwtCrypto = new JwtCrypto();
|
||||||
$this->cryptoInterface = $jwtCrypto;
|
$this->cryptoInterface = $jwtCrypto;
|
||||||
break;
|
break;
|
||||||
|
case 'admin-jwt':
|
||||||
|
$jwtCrypto = new JwtCrypto();
|
||||||
|
$this->cryptoInterface = $jwtCrypto;
|
||||||
|
$this->cryptoInterface->type = $type;
|
||||||
|
break;
|
||||||
case 'admin-password':
|
case 'admin-password':
|
||||||
$adminCrypto = new AdminPasswordCrypto();
|
$adminCrypto = new AdminPasswordCrypto();
|
||||||
$this->cryptoInterface = $adminCrypto;
|
$this->cryptoInterface = $adminCrypto;
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ class JwtCrypto implements CryptoInterface
|
|||||||
*/
|
*/
|
||||||
public string $data = '';
|
public string $data = '';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录类型
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
public string $type = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加密 key
|
* 加密 key
|
||||||
* @var string
|
* @var string
|
||||||
@@ -41,7 +47,6 @@ class JwtCrypto implements CryptoInterface
|
|||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->key = config('system.jwt_key');
|
$this->key = config('system.jwt_key');
|
||||||
$this->expire = (int)config('system.jwt_expire');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,6 +55,16 @@ class JwtCrypto implements CryptoInterface
|
|||||||
*/
|
*/
|
||||||
public function encrypt(): string
|
public function encrypt(): string
|
||||||
{
|
{
|
||||||
|
switch ($this->type) {
|
||||||
|
case 'admin-jwt':
|
||||||
|
$this->expire = (int)config('system.admin_jwt_expire');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
case 'jwt':
|
||||||
|
$this->expire = (int)config('system.jwt_expire');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$time = time();
|
$time = time();
|
||||||
$payload = [
|
$payload = [
|
||||||
|
|||||||
56
app/Middleware/Admin/JwtAuthMiddleware.php
Normal file
56
app/Middleware/Admin/JwtAuthMiddleware.php
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Middleware\Admin;
|
||||||
|
|
||||||
|
use App\Cache\Redis\Admin\UserCache;
|
||||||
|
use App\Constants\AdminCode;
|
||||||
|
use App\Lib\AdminReturn;
|
||||||
|
use App\Lib\Crypto\CryptoFactory;
|
||||||
|
use Hyperf\Context\Context;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Psr\Http\Server\MiddlewareInterface;
|
||||||
|
use Psr\Http\Server\RequestHandlerInterface;
|
||||||
|
use Hyperf\HttpServer\Contract\ResponseInterface as HttpResponse;
|
||||||
|
|
||||||
|
class JwtAuthMiddleware implements MiddlewareInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected HttpResponse $response,
|
||||||
|
protected AdminReturn $apiReturn,
|
||||||
|
protected CryptoFactory $cryptoFactory,
|
||||||
|
protected UserCache $userCache,
|
||||||
|
){}
|
||||||
|
|
||||||
|
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
|
||||||
|
{
|
||||||
|
// 获取头部token
|
||||||
|
$authorization = $request->getHeaderLine('Authorization');
|
||||||
|
|
||||||
|
if (empty($authorization)) {
|
||||||
|
return $this->response->json(
|
||||||
|
$this->apiReturn->error(AdminCode::getMessage(AdminCode::LOGIN_ERROR), AdminCode::LOGIN_ERROR)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$authorization = str_replace("Bearer ", "", $authorization);
|
||||||
|
$userJwt = $this->cryptoFactory->cryptoClass('admin-jwt', $authorization)->decrypt();
|
||||||
|
if (empty($userJwt)) {
|
||||||
|
return $this->response->json(
|
||||||
|
$this->apiReturn->error(AdminCode::getMessage(AdminCode::LOGIN_TOKEN_ERROR), AdminCode::LOGIN_TOKEN_ERROR)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//单点登录
|
||||||
|
if ($this->userCache->getAdminToken($userJwt['data']->id) != $authorization) {
|
||||||
|
return $this->response->json(
|
||||||
|
$this->apiReturn->error(AdminCode::getMessage(AdminCode::LOGIN_TOKEN_ERROR), AdminCode::LOGIN_TOKEN_ERROR)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Context::set('admin_id',$userJwt['data']->id);
|
||||||
|
Context::set('role_id',$userJwt['data']->role);
|
||||||
|
|
||||||
|
return $handler->handle($request);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,7 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Service\Admin\User;
|
namespace App\Service\Admin\User;
|
||||||
|
|
||||||
|
use App\Cache\Redis\Admin\UserCache;
|
||||||
use App\Constants\Admin\UserCode;
|
use App\Constants\Admin\UserCode;
|
||||||
use App\Constants\AdminCode;
|
use App\Constants\AdminCode;
|
||||||
use App\Exception\AdminException;
|
use App\Exception\AdminException;
|
||||||
@@ -19,6 +20,9 @@ use App\Model\AdminUser;
|
|||||||
use App\Service\Admin\BaseService;
|
use App\Service\Admin\BaseService;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Hyperf\Di\Annotation\Inject;
|
use Hyperf\Di\Annotation\Inject;
|
||||||
|
use Psr\Container\ContainerExceptionInterface;
|
||||||
|
use Psr\Container\NotFoundExceptionInterface;
|
||||||
|
use function Hyperf\Config\config;
|
||||||
|
|
||||||
class LoginService extends BaseService
|
class LoginService extends BaseService
|
||||||
{
|
{
|
||||||
@@ -37,10 +41,19 @@ class LoginService extends BaseService
|
|||||||
#[Inject]
|
#[Inject]
|
||||||
protected CryptoFactory $cryptoFactory;
|
protected CryptoFactory $cryptoFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 注入用户缓存
|
||||||
|
* @var UserCache $userCache
|
||||||
|
*/
|
||||||
|
#[Inject]
|
||||||
|
protected UserCache $userCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 后台登录
|
* 后台登录
|
||||||
* @return array
|
* @return array
|
||||||
* @throws Exception
|
* @throws ContainerExceptionInterface
|
||||||
|
* @throws NotFoundExceptionInterface
|
||||||
|
* @throws \RedisException
|
||||||
*/
|
*/
|
||||||
public function handle(): array
|
public function handle(): array
|
||||||
{
|
{
|
||||||
@@ -60,11 +73,14 @@ class LoginService extends BaseService
|
|||||||
if (!$userInfo->save()) throw new AdminException('登录失败');
|
if (!$userInfo->save()) throw new AdminException('登录失败');
|
||||||
|
|
||||||
//生成 token
|
//生成 token
|
||||||
$token = $this->cryptoFactory->cryptoClass('jwt',json_encode([
|
$token = $this->cryptoFactory->cryptoClass('admin-jwt',json_encode([
|
||||||
'id' => $userInfo->id,
|
'id' => $userInfo->id,
|
||||||
'role' => $userInfo->role_id,
|
'role' => $userInfo->role_id,
|
||||||
]))->encrypt();
|
]))->encrypt();
|
||||||
|
|
||||||
|
//单点登录
|
||||||
|
$this->userCache->setAdminToken($userInfo->id, $token, (int)config('system.admin_jwt_expire'));
|
||||||
|
|
||||||
return $this->return->success('success',[
|
return $this->return->success('success',[
|
||||||
'token' => $token,
|
'token' => $token,
|
||||||
'info' => [
|
'info' => [
|
||||||
|
|||||||
8
app/Service/ServiceTrait/Admin/GetUserInfoTrait.php
Normal file
8
app/Service/ServiceTrait/Admin/GetUserInfoTrait.php
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Service\ServiceTrait\Admin;
|
||||||
|
|
||||||
|
trait GetUserInfoTrait
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,4 +17,6 @@ return [
|
|||||||
'jwt_key' => env('JWT_KEY','hhl@shenzhen'),
|
'jwt_key' => env('JWT_KEY','hhl@shenzhen'),
|
||||||
// jwt 过期时间
|
// jwt 过期时间
|
||||||
'jwt_expire' => env('JWT_EXPIRE',86400 * 30),
|
'jwt_expire' => env('JWT_EXPIRE',86400 * 30),
|
||||||
|
// admin jwt 过期时间
|
||||||
|
'admin_jwt_expire' => env('ADMIN_JWT_EXPIRE',86400 * 30),
|
||||||
];
|
];
|
||||||
@@ -1,5 +1,17 @@
|
|||||||
### 角色详情
|
### 登录
|
||||||
GET {{host}}/admin/auth/role?role_id=1
|
POST {{host}}/admin/login/user
|
||||||
Content-Type: application/x-www-form-urlencoded
|
Content-Type: application/x-www-form-urlencoded
|
||||||
|
|
||||||
|
account=13632877014&password=123456
|
||||||
|
|
||||||
|
> {%
|
||||||
|
client.global.set("admin_token", response.body.data.token);
|
||||||
|
%}
|
||||||
|
|
||||||
|
### 角色详情
|
||||||
|
GET {{host}}/admin/auth/role?role_id=1
|
||||||
|
Content-Type: application/json
|
||||||
|
Authorization: Bearer {{admin_token}}
|
||||||
|
|
||||||
|
|
||||||
###
|
###
|
||||||
Reference in New Issue
Block a user