设置缓存

This commit is contained in:
zhang zhuo 2025-12-05 14:28:14 +08:00
parent 1213f86045
commit 81ee0d339d
13 changed files with 157 additions and 44 deletions

View File

@ -15,6 +15,7 @@ use Hyperf\Di\Aop\ProceedingJoinPoint;
use Hyperf\Di\Exception\AnnotationException;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\HttpServer\Contract\ResponseInterface;
use Psr\SimpleCache\CacheInterface;
#[Aspect]
class AuthAspect extends AbstractAspect
@ -23,6 +24,8 @@ class AuthAspect extends AbstractAspect
protected RequestInterface $request;
#[Inject]
protected ResponseInterface $response;
#[Inject]
protected CacheInterface $cache;
public array $annotations = [
Auth::class
@ -81,9 +84,7 @@ class AuthAspect extends AbstractAspect
*/
protected function checkPermission(string $auth, string $method, array $account): bool {
if ($auth == "*" || $account['master_flag']) return true;
$container = ApplicationContext::getContainer();
$redis = $container->get(\Hyperf\Redis\Redis::class);
$auths = $redis->get("AUTH:".$account['account_id']);
$auths = $this->cache->get("AUTH:".$account['account_id']);
if (!$auths) return false;
$auths = json_decode($auths, true);
if (!empty($auths)) {

View File

@ -10,6 +10,7 @@ use Hyperf\HttpServer\Contract\ResponseInterface;
use Hyperf\View\RenderInterface;
use Psr\Container\ContainerInterface;
use Psr\EventDispatcher\EventDispatcherInterface;
use Psr\SimpleCache\CacheInterface;
abstract class AbstractController
{
@ -25,6 +26,9 @@ abstract class AbstractController
#[Inject]
protected EventDispatcherInterface $eventDispatcher;
#[Inject]
protected CacheInterface $cache;
#[Inject]
protected RenderInterface $render;
}

View File

@ -13,7 +13,6 @@ use App\Model\Online;
use App\Utils\Param;
use App\Utils\Str;
use App\Utils\Token;
use Hyperf\Context\ApplicationContext;
use Hyperf\Filesystem\FilesystemFactory;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
@ -21,6 +20,7 @@ use Hyperf\HttpServer\Annotation\PostMapping;
use MathCaptcha\Captcha;
use App\Request\Account as aRequest;
use function Hyperf\Config\config;
use function Hyperf\Translation\__;
#[Controller(prefix: "admin")]
class Login extends Base
@ -36,9 +36,7 @@ class Login extends Base
$code = $ca->setDigits(1)->setPoint(100)->setLine(2)->setFontSize(24)->result();
$image = $ca->base64();
// 缓存
$container = ApplicationContext::getContainer();
$redis = $container->get(\Hyperf\Redis\Redis::class);
$redis->set("VER:" . $uuid, md5((string)$code), 300);
$this->cache->set("VER:" . $uuid, md5((string)$code), 300);
return $this->success(compact("uuid", "image"));
}
@ -51,17 +49,15 @@ class Login extends Base
$request = $this->container->get(aRequest::class);
$request->scene('login')->validateResolved();
// 验证码
$container = ApplicationContext::getContainer();
$redis = $container->get(\Hyperf\Redis\Redis::class);
$code = $redis->get("VER:" . $param['uuid']);
$code = $this->cache->get("VER:" . $param['uuid']);
if (!$code) {
return $this->error("验证码已失效!");
return $this->error(__("login.codeExpired"));
}
if ($code != md5($param['code'])) {
return $this->error("验证码填写错误!");
return $this->error(__("login.codeIncorrect"));
}
// 验证一次就失效
$redis->del("VER:" . $param['uuid']);
$this->cache->delete("VER:" . $param['uuid']);
// 查找用户
$account = Account::getByUsername($param['username'], ['account_id', 'username', 'password', 'salt', 'status', 'account_type', 'belong_id', 'master_flag', 'nickname', 'dept_id']);
// 总后台和代理登录
@ -91,8 +87,8 @@ class Login extends Base
$this->eventDispatcher->dispatch(new LogEvent($tData));
// 根据账号所属角色缓存相应的权限数据
$auths = Account::getAuths($account['account_id'], $account['account_type'], $account['master_flag']);
$redis->set("AUTH:" . $account['account_id'], json_encode($auths));
$redis->set("USER:" . $uuid, json_encode($tData), config("jwt.ttl"));
$this->cache->set("AUTH:" . $account['account_id'], json_encode($auths));
$this->cache->set("USER:" . $uuid, json_encode($tData), config("jwt.ttl"));
// 生成token
return $this->success(compact("token"));
}
@ -116,10 +112,8 @@ class Login extends Base
public function logout()
{
// 退出登录状态
$container = ApplicationContext::getContainer();
$redis = $container->get(\Hyperf\Redis\Redis::class);
$redis->del("USER:" . $this->uuid());
$redis->del("AUTH:" . $this->account()['account_id']);
$this->cache->delete("USER:" . $this->uuid());
$this->cache->delete("AUTH:" . $this->account()['account_id']);
// 设置离线
Online::leave($this->uuid());
return $this->success("登出成功");

View File

@ -32,6 +32,7 @@ use App\Model\DictData as ddModel;
use App\Request\DictData as ddRequest;
use App\Model\Translation as tsModel;
use App\Request\Translation as tsRequest;
use App\Service\ConfigCacheService;
use App\Utils\AppInfoHelper;
use App\Utils\CpuHelper;
use App\Utils\DiskInfoHelper;
@ -388,10 +389,8 @@ class System extends Base
if (empty($online) || $online['status'] == 0) {
return $this->success("用户已不在线");
}
$container = ApplicationContext::getContainer();
$redis = $container->get(\Hyperf\Redis\Redis::class);
$redis->del("USER:" . $param['session_id']);
$redis->del("AUTH:" . $online['account_id']);
$this->cache->delete("USER:" . $param['session_id']);
$this->cache->delete("AUTH:" . $online['account_id']);
// 设置离线
oModel::leave($param['session_id']);
return $this->success("强退成功");
@ -800,7 +799,12 @@ class System extends Base
$request = $this->container->get(scRequest::class);
$request->scene('add')->validateResolved();
$data = Param::only(["config_name", "config_key", "config_value", "remark"]);
return $this->toAjax(scModel::add($data));
$res = scModel::add($data);
if (!$res) {
return $this->error();
}
(new ConfigCacheService())->setItem($data['config_key'], $data['config_value']);
return $this->success();
}
#[PutMapping(path: "system_config/edit")]
@ -810,7 +814,16 @@ class System extends Base
$request = $this->container->get(scRequest::class);
$request->scene('edit')->validateResolved();
$data = Param::only(["config_id", "config_name", "config_key", "config_value", "remark"]);
return $this->toAjax(scModel::edit($data));
// 删除原来的缓存
$info = scModel::getById($data['config_id'],['config_key']);
(new ConfigCacheService())->removeItem($info['config_key']);
// 变更数据
$res = scModel::edit($data);
if (!$res) {
return $this->error();
}
(new ConfigCacheService())->setItem($data['config_key'], $data['config_value']);
return $this->success();
}
#[DeleteMapping(path: "system_config/del")]
@ -818,6 +831,8 @@ class System extends Base
public function systemConfigDel()
{
$ids = $this->request->input("ids");
$data = scModel::whereIn("config_id", $ids)->pluck("config_key")->toArray();
(new ConfigCacheService())->multipleRemoveItem($data);
return $this->toAjax(scModel::del($ids));
}

View File

@ -12,6 +12,7 @@ use Hyperf\Contract\OnCloseInterface;
use Hyperf\Contract\OnMessageInterface;
use Hyperf\Contract\OnOpenInterface;
use Hyperf\WebSocketServer\Context;
use Psr\SimpleCache\CacheInterface;
/**
* 商户端socket
@ -44,10 +45,9 @@ class WebSocket implements OnMessageInterface, OnOpenInterface, OnCloseInterface
{
$token = $request->get['Authorization'];
$result = Token::parseToken(str_replace("Bearer ", "", $token));
$container = ApplicationContext::getContainer();
$redis = $container->get(\Hyperf\Redis\Redis::class);
$account = !empty($result) ? json_decode($redis->get("USER:" . $result['uuid']), true) : null;
$cache = $container->get(CacheInterface::class);
$account = !empty($result) ? json_decode($cache->get("USER:" . $result['uuid']), true) : null;
if (!empty($account)) {
Online::live($result['uuid'], $request->fd);
Context::set('account', $account);

View File

@ -2,6 +2,8 @@
namespace App\Listener;
use App\Service\ConfigCacheService;
use App\Service\DictCacheService;
use App\Utils\AppInfoHelper;
use Hyperf\Event\Annotation\Listener;
use Hyperf\Event\Contract\ListenerInterface;
@ -19,5 +21,7 @@ class AppBootListener implements ListenerInterface
{
// 在框架启动时初始化启动时间
AppInfoHelper::initStartTime();
// 初始化配置项缓存
(new ConfigCacheService())->loadAll();
}
}

View File

@ -13,6 +13,7 @@ use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\SimpleCache\CacheInterface;
use function Hyperf\Config\config;
class JWTMiddleware implements MiddlewareInterface
@ -20,11 +21,17 @@ class JWTMiddleware implements MiddlewareInterface
/**
* @var ContainerInterface
*/
protected $container;
protected ContainerInterface $container;
public function __construct(ContainerInterface $container)
/**
* @var CacheInterface
*/
protected CacheInterface $cache;
public function __construct(ContainerInterface $container, CacheInterface $cache)
{
$this->container = $container;
$this->cache = $cache;
}
/**
@ -36,7 +43,6 @@ class JWTMiddleware implements MiddlewareInterface
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$container = ApplicationContext::getContainer();
$redis = $container->get(\Hyperf\Redis\Redis::class);
// 管理端 和 商户端
$request = $request->withAttribute("isLogin", false);
$request = $request->withAttribute("account", []);
@ -45,7 +51,7 @@ class JWTMiddleware implements MiddlewareInterface
$token = $request->getHeaderLine("Authorization", "");
$result = Token::parseToken(str_replace("Bearer ", "", $token));
if (!empty($result)) {
$user = $redis->get("USER:" . $result['uuid']);
$user = $this->cache->get("USER:" . $result['uuid']);
if (!empty($user)) {
$account = json_decode($user, true);
}
@ -54,7 +60,7 @@ class JWTMiddleware implements MiddlewareInterface
if (!empty($account)) {
// 是否登录
$request = $request->withAttribute("isLogin", true);
$account = json_decode($redis->get("USER:" . $result['uuid']), true);
$account = json_decode($this->cache->get("USER:" . $result['uuid']), true);
// 账号ID
$request = $request->withAttribute("account_id", $account['account_id']);
// 基础信息
@ -71,7 +77,7 @@ class JWTMiddleware implements MiddlewareInterface
$newToken = Token::buildToken(['uuid' => $result['uuid'], 'time' => time() + config("jwt.ttl")], config("jwt.ttl"));
$response = $response->withHeader('X-Token-Refresh', $newToken);
$response = $response->withHeader('X-Token-Expire', config("jwt.ttl"));
$redis->set("USER:" . $result['uuid'], json_encode($account), config("jwt.ttl"));
$this->cache->set("USER:" . $result['uuid'], json_encode($account), config("jwt.ttl"));
}
return $response;
}

View File

@ -50,4 +50,19 @@ class Dict extends Model
{
return self::select(["dict_id", "dict_name"])->get()->toArray();
}
public static function getAll()
{
return self::with(["values" => function ($query) {
$query->select(["dict_label", "dict_value", "is_default"]);
}])
->select(["dict_type", "dict_id"])
->get()
->toArray();
}
protected function values()
{
return $this->hasMany(DictData::class, "dict_id", "dict_id");
}
}

View File

@ -4,9 +4,8 @@ declare(strict_types=1);
namespace App\Model;
use Hyperf\Context\ApplicationContext;
use App\Utils\Cache;
use Hyperf\DbConnection\Db;
use function Hyperf\Config\config;
/**
* @property int $menu_id
@ -27,6 +26,7 @@ use function Hyperf\Config\config;
*/
class Menu extends Model
{
use Cache;
/**
* The table associated with the model.
*/
@ -90,9 +90,7 @@ class Menu extends Model
public static function getTitleByCache($method, $flag, $account_type)
{
// 先从缓存取数据,缓存中没则从数据库中取数据
$container = ApplicationContext::getContainer();
$redis = $container->get(\Hyperf\Redis\Redis::class);
$menus = $redis->get("AUTH:" . $account_type);
$menus = self::cache()->get("AUTH:" . $account_type);
if (!empty($menus) && isset($menus[$method . ":" . $flag])) {
// 存在则从缓存中读取
return $menus[$method . ":" . $flag];
@ -114,7 +112,7 @@ class Menu extends Model
/**
* Author: cfn <cfn@leapy.cn>
* @param $account_type
* @return bool|\Redis
* @return bool
*/
private static function setCache($account_type)
{
@ -126,9 +124,7 @@ class Menu extends Model
foreach ($arr as $v) {
$newArr[$v['title']] = $v['flag'];
}
$container = ApplicationContext::getContainer();
$redis = $container->get(\Hyperf\Redis\Redis::class);
return $redis->set("AUTH:" . $account_type, json_encode($newArr), 72 * 60 * 60);
return self::cache()->set("AUTH:" . $account_type, json_encode($newArr), 72 * 60 * 60);
}
/**

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace App\Model;
use App\Utils\Cache;
use App\Utils\Crud;
use Hyperf\Database\Model\SoftDeletes;
use Hyperf\DbConnection\Model\Model as BaseModel;

View File

@ -0,0 +1,63 @@
<?php
namespace App\Service;
use Hyperf\Context\ApplicationContext;
use Psr\SimpleCache\CacheInterface;
use App\Model\SystemConfig as scModel;
class ConfigCacheService
{
protected CacheInterface $cache;
protected string $prefix = 'config:';
public function __construct()
{
$this->cache = ApplicationContext::getContainer()->get(CacheInterface::class);
}
public function loadAll(): void
{
// 加载所有配置项
$configs = scModel::pluck("config_value", "config_key")->toArray();
if (!empty($configs)) {
$configs = array_combine(
array_map(fn($k) => $this->prefix . "$k", array_keys($configs)),
$configs
);
$this->cache->setMultiple($configs);
}
}
public function clearAll(): void
{
// 加载所有配置项
$configs = scModel::pluck("config_key")->toArray();
if (!empty($configs)) {
$keys = array_map(fn($k) => $this->prefix . "$k", $configs);
$this->cache->deleteMultiple($keys);
}
}
public function setItem(string $key, string|null $value): bool
{
return $this->cache->set($this->prefix . $key, $value);
}
public function getItem(string $key): mixed
{
return $this->cache->get($this->prefix . $key);
}
public function removeItem(string $key): bool
{
return $this->cache->delete($this->prefix . $key);
}
public function multipleRemoveItem(array $keys): bool
{
if (count($keys) === 0) return true;
$keys = array_map(fn($k) => $this->prefix . "$k", $keys);
return $this->cache->deleteMultiple($keys);
}
}

14
app/Utils/Cache.php Normal file
View File

@ -0,0 +1,14 @@
<?php
namespace App\Utils;
use Hyperf\Context\ApplicationContext;
use Psr\SimpleCache\CacheInterface;
trait Cache
{
public static function cache(): CacheInterface
{
return ApplicationContext::getContainer()->get(CacheInterface::class);
}
}

View File

@ -13,7 +13,7 @@ return [
'default' => [
'driver' => Hyperf\Cache\Driver\RedisDriver::class,
'packer' => Hyperf\Codec\Packer\PhpSerializerPacker::class,
'prefix' => 'c:',
'prefix' => 'pi:',
'skip_cache_results' => [],
],
];