diff --git a/server/app/adminapi/controller/BaseAdminController.php b/server/app/adminapi/controller/BaseAdminController.php index 4be299fc540124962ef76e0d8a7d343270014f9c..40df4b3e59c4c46a4932c44798dfb89e4ba9e4ae 100644 --- a/server/app/adminapi/controller/BaseAdminController.php +++ b/server/app/adminapi/controller/BaseAdminController.php @@ -17,11 +17,17 @@ class BaseAdminController extends BaseLikeAdminController public function initialize() { parent::initialize(); - $this->adminId = 0; - $this->adminInfo = []; - if (isset($this->request->adminInfo) && $this->request->adminInfo) { - $this->adminInfo = $this->request->adminInfo; - $this->adminId = $this->request->adminInfo['admin_id']; - } + } + public function setAdmin($adminId,$adminInfo): void + { + $this->adminId = $adminId; + $this->adminInfo = $adminInfo; + } + public function getAdmin(): array + { + return [ + $this->adminId, + $this->adminInfo + ]; } } \ No newline at end of file diff --git a/server/app/adminapi/listener/OperationLog.php b/server/app/adminapi/listener/OperationLog.php index 129fa00a92d3f45e52ddee6e081863273777ed99..539cff394018cea549a4050a9058f0b64db306c3 100644 --- a/server/app/adminapi/listener/OperationLog.php +++ b/server/app/adminapi/listener/OperationLog.php @@ -5,6 +5,7 @@ namespace app\adminapi\listener; use ReflectionClass; +use support\Log; use Webman\Http\Request; use think\Exception; use Webman\Http\Response; @@ -13,28 +14,32 @@ class OperationLog { /** * @notes 管理员操作日志 - * @param $response - * @return bool|void + * @param Request $request + * @param Response $response + * @return bool * @throws \ReflectionException * @author bingo * @date 2022/4/8 17:09 */ - public static function handle(Request $request, Response $response) + public static function handle(Request $request, Response $response): bool { + $controllerObject = make($request->controller); + [$adminId,$adminInfo] = $controllerObject->getAdmin(); + //需要登录的接口,无效访问时不记录 - if (!$request->controllerObject||!$request->controllerObject->isNotNeedLogin($request->action) && empty($request->adminInfo)) { - return; + if (!$controllerObject||!$controllerObject->isNotNeedLogin($request->action) && empty($adminInfo)) { + return false; } $pathLower = strtolower($request->path()); //不记录日志操作 if (str_contains($pathLower,"/api/")||$pathLower === '/adminapi/setting/system/log') { - return; + return false; } //获取操作注解 - $notes = ''; + $notes = '无法获取操作名称,请给控制器方法注释'; try { - $re = new ReflectionClass($request->controllerObject); + $re = new ReflectionClass($controllerObject); $doc = $re->getMethod($request->action)->getDocComment(); if (empty($doc)) { throw new Exception('请给控制器方法注释'); @@ -42,7 +47,11 @@ class OperationLog preg_match('/\s(\w+)/u', $re->getMethod($request->action)->getDocComment(), $values); $notes = $values[0]; } catch (Exception $e) { - $notes = $notes ?: '无法获取操作名称,请给控制器方法注释'; + Log::error("日志记录错误",[ + 'path'=>$request->path(), + 'title'=>"无法获取操作名称,请给控制器方法注释", + 'msg'=>$e->getMessage(), + ]); } $params = $request->all(); @@ -60,20 +69,30 @@ class OperationLog if (isset($params['export']) && $params['export'] == 2) { $notes .= '-数据导出'; } - \app\common\model\OperationLog::destroy(function ($query) { - $query->where('create_time','<',strtotime("-15 day")); - },true); //记录日志 $systemLog = new \app\common\model\OperationLog(); - $systemLog->admin_id = $request->adminInfo['admin_id'] ?? 0; - $systemLog->admin_name = $request->adminInfo['name'] ?? ''; + $systemLog->admin_id = $adminInfo['admin_id'] ?? 0; + $systemLog->admin_name = $adminInfo['name'] ?? ''; $systemLog->action = $notes; - $systemLog->account = $request->adminInfo['account'] ?? ''; + $systemLog->account = $adminInfo['account'] ?? ''; $systemLog->url = $request->path(); - $systemLog->type = $request->method() ? 'GET' : 'POST'; + $systemLog->type = $request->method(); $systemLog->params = json_encode($params, true); $systemLog->ip = getRealIP(); - $systemLog->result = $response->rawBody(); - return $systemLog->save(); + $systemLog->result = 0; + // 正则表达式匹配指定key的值 + preg_match('/"code":\s*"([^"]+)"/', $response->rawBody(), $matches); + if (isset($matches[1])) { + $systemLog->result = $matches[1]; + } + $res = $systemLog->save(); + Log::info("日志记录",[ + 'id'=>$systemLog->id, + 'adminId'=>$systemLog->admin_id, + 'url'=>$systemLog->url, + 'params'=>$systemLog->params, + 'result'=>$response->rawBody(), + ]); + return $res; } } \ No newline at end of file diff --git a/server/app/adminapi/lists/BaseAdminDataLists.php b/server/app/adminapi/lists/BaseAdminDataLists.php index 5469a934bc984d21508a6d3abac94f69b9b7c3eb..748ad346deacf905dddb1939edfc0923a8447814 100644 --- a/server/app/adminapi/lists/BaseAdminDataLists.php +++ b/server/app/adminapi/lists/BaseAdminDataLists.php @@ -31,8 +31,8 @@ abstract class BaseAdminDataLists extends BaseDataLists public function __construct() { parent::__construct(); - $this->adminInfo = $this->request->adminInfo; - $this->adminId = $this->request->adminId; + $controllerObject = make($this->request->controller); + [$this->adminId,$this->adminInfo] = $controllerObject->getAdmin(); } diff --git a/server/app/adminapi/middleware/AuthMiddleware.php b/server/app/adminapi/middleware/AuthMiddleware.php index 0f3b7ded58426f5fbb564c6898fef486781ce1af..ff8bd24ff2454280b0c34ae59d0b0a3ae5899082 100644 --- a/server/app/adminapi/middleware/AuthMiddleware.php +++ b/server/app/adminapi/middleware/AuthMiddleware.php @@ -15,17 +15,19 @@ class AuthMiddleware implements MiddlewareInterface { public function process(Request $request, callable $handler): Response { + $controllerObject = make($request->controller); + [$adminId,$adminInfo] = $controllerObject->getAdmin(); //不登录访问,无需权限验证 - if ($request->controllerObject->isNotNeedLogin($request->action)) { + if ($controllerObject->isNotNeedLogin($request->action)) { return $handler($request); } //系统默认超级管理员,无需权限验证 - if (1 === $request->adminInfo['root']) { + if (1 === $adminInfo['root']) { return $handler($request); } - $adminAuthCache = new AdminAuthCache($request->adminInfo['admin_id']); + $adminAuthCache = new AdminAuthCache($adminId); // 当前访问路径 $accessUri = strtolower($request->controller . '/' . $request->action); diff --git a/server/app/adminapi/middleware/InitMiddleware.php b/server/app/adminapi/middleware/InitMiddleware.php index a57b6376c3767c3b68c70d95abc259ae67125190..e9b2bcb6943e28fb30adcd4576dfd919c1d94f3d 100644 --- a/server/app/adminapi/middleware/InitMiddleware.php +++ b/server/app/adminapi/middleware/InitMiddleware.php @@ -6,10 +6,8 @@ namespace app\adminapi\middleware; use app\adminapi\controller\BaseAdminController; use app\common\exception\ControllerExtendException; -use ReflectionClass; use think\exception\ClassNotFoundException; use app\common\exception\HttpException; -use Webman\App; use Webman\Http\Request; use Webman\Http\Response; use Webman\MiddlewareInterface; @@ -31,14 +29,11 @@ class InitMiddleware implements MiddlewareInterface //使用容器中的控制器对象 $controllerClass = make($request->controller); if (($controllerClass instanceof BaseAdminController) === false) { - throw new ControllerExtendException($request->controller, '404'); + throw new ControllerExtendException($request->controller, BaseAdminController::class); } - //创建控制器对象 - $request->controllerObject = $controllerClass; + $controllerClass->setAdmin(0,[]); } catch (ClassNotFoundException $e) { - throw new HttpException(404, 'controller not exists:' . $e->getClass()); - } catch (\ReflectionException $e) { - throw new HttpException(404, 'controller init exists:' . $e->getMessage()); + throw new HttpException($e->getMessage().' controller not exists:' . $e->getClass(),404); } return $handler($request); } diff --git a/server/app/adminapi/middleware/LoginMiddleware.php b/server/app/adminapi/middleware/LoginMiddleware.php index 1fea132b215188adf2620deffe9d76853d5b4f1d..0005cce17e493f1239f352e7a4fa132a1393f06d 100644 --- a/server/app/adminapi/middleware/LoginMiddleware.php +++ b/server/app/adminapi/middleware/LoginMiddleware.php @@ -25,8 +25,9 @@ class LoginMiddleware implements MiddlewareInterface public function process(Request $request, callable $handler): Response { $token = $request->header('token'); + $controllerObject = make($request->controller); //判断接口是否免登录 - $isNotNeedLogin = $request->controllerObject->isNotNeedLogin($request->action); + $isNotNeedLogin = $controllerObject->isNotNeedLogin($request->action); //不直接判断$isNotNeedLogin结果,使不需要登录的接口通过,为了兼容某些接口可以登录或不登录访问 if (empty($token) && !$isNotNeedLogin) { @@ -55,9 +56,8 @@ class LoginMiddleware implements MiddlewareInterface } //给request赋值,用于控制器 - $request->adminInfo = $adminInfo; - $request->adminId = $adminInfo['admin_id'] ?? 0; - + $adminId = $adminInfo['admin_id'] ?? 0; + $controllerObject->setAdmin($adminId,$adminInfo); return $handler($request); } } \ No newline at end of file diff --git a/server/app/api/controller/BaseApiController.php b/server/app/api/controller/BaseApiController.php index 1888316852d57f3651fa4cfad295a7db08732e3a..b2e5cfb817f8f34ae9412996d48f12a0f43fde21 100644 --- a/server/app/api/controller/BaseApiController.php +++ b/server/app/api/controller/BaseApiController.php @@ -24,11 +24,17 @@ class BaseApiController extends BaseLikeAdminController public function initialize() { parent::initialize(); - $this->userId = 0; - $this->userInfo = []; - if (isset($this->request->userInfo) && $this->request->userInfo) { - $this->userInfo = $this->request->userInfo; - $this->userId = $this->request->userInfo['user_id']; - } + } + public function setUser($userId,$userInfo): void + { + $this->userId = $userId; + $this->userInfo = $userInfo; + } + public function getUser(): array + { + return [ + $this->userId, + $this->userInfo + ]; } } \ No newline at end of file diff --git a/server/app/api/lists/BaseApiDataLists.php b/server/app/api/lists/BaseApiDataLists.php index fcf409eb56875ec0aa78c3bc15155e4891f5ce64..c1c3f2a74e1bc065ac22251a3b03a030fa526e41 100644 --- a/server/app/api/lists/BaseApiDataLists.php +++ b/server/app/api/lists/BaseApiDataLists.php @@ -26,10 +26,8 @@ abstract class BaseApiDataLists extends BaseDataLists public function __construct() { parent::__construct(); - if (isset($this->request->userInfo) && $this->request->userInfo) { - $this->userInfo = $this->request->userInfo; - $this->userId = $this->request->userId; - } + $controllerObject = make($this->request->controller); + [$this->userId,$this->userInfo] = $controllerObject->getUser(); $this->export = $this->request->get('export', ''); } diff --git a/server/app/api/middleware/InitMiddleware.php b/server/app/api/middleware/InitMiddleware.php index 8a818bc6cc02de006d11925aedf9e84653ba81b4..e4d719aa28d6effb49912b3fb696e082d54f2d02 100644 --- a/server/app/api/middleware/InitMiddleware.php +++ b/server/app/api/middleware/InitMiddleware.php @@ -19,12 +19,7 @@ namespace app\api\middleware; use app\api\controller\BaseApiController; use app\common\exception\ControllerExtendException; use app\common\exception\HttpException; -use Psr\Container\ContainerExceptionInterface; -use Psr\Container\NotFoundExceptionInterface; -use ReflectionClass; use think\exception\ClassNotFoundException; -use Webman\App; -use Webman\Container; use Webman\Http\Request; use Webman\Http\Response; use Webman\MiddlewareInterface; @@ -47,14 +42,11 @@ class InitMiddleware implements MiddlewareInterface try { $controllerClass = make($request->controller); if (($controllerClass instanceof BaseApiController) === false) { - throw new ControllerExtendException($request->controller, '404'); + throw new ControllerExtendException($request->controller, BaseApiController::class); } - //创建控制器对象 - $request->controllerObject = $controllerClass; + $controllerClass->setUser(0,[]); } catch (ClassNotFoundException $e) { - throw new HttpException(404, 'controller not exists:' . $e->getClass()); - } catch (NotFoundExceptionInterface $e) { - throw new HttpException(404, 'controller not exists:' . $e->getMessage()); + throw new HttpException($e->getMessage().' controller not exists:' . $e->getClass(),404); } return $handler($request); } diff --git a/server/app/api/middleware/LoginMiddleware.php b/server/app/api/middleware/LoginMiddleware.php index 5e88b8ec157ef26afb5d023f4f4c8b0e540973bc..e06c7a5a93d7a636a5c4e45ec66248a492cda5cb 100644 --- a/server/app/api/middleware/LoginMiddleware.php +++ b/server/app/api/middleware/LoginMiddleware.php @@ -30,8 +30,9 @@ class LoginMiddleware implements MiddlewareInterface { // TODO: Implement process() method. $token = $request->header('token'); + $controllerObject = make($request->controller); //判断接口是否免登录 - $isNotNeedLogin = $request->controllerObject->isNotNeedLogin($request->action); + $isNotNeedLogin = $controllerObject->isNotNeedLogin($request->action); //不直接判断$isNotNeedLogin结果,使不需要登录的接口通过,为了兼容某些接口可以登录或不登录访问 if (empty($token) && !$isNotNeedLogin) { @@ -61,8 +62,8 @@ class LoginMiddleware implements MiddlewareInterface } //给request赋值,用于控制器 - $request->userInfo = $userInfo; - $request->userId = $userInfo['user_id'] ?? 0; + $userId = $userInfo['user_id'] ?? 0; + $controllerObject->setUser($userId,$userInfo); return $handler($request); } diff --git a/server/app/common/exception/HttpException.php b/server/app/common/exception/HttpException.php index 409c64d8f2287ec5808bb4eb03655319c4b9a93e..703b3ae8044c319bbb17407b8880ea3b7b2ee702 100644 --- a/server/app/common/exception/HttpException.php +++ b/server/app/common/exception/HttpException.php @@ -11,7 +11,8 @@ class HttpException extends \RuntimeException public function __construct($message = "", $code = 0, $header=[],Throwable $previous = null) { - $this->response = json(json_decode($message,true)); + $header = array_merge($header,['Content-Type'=>'application/json']); + $this->response = response($message,$code,$header); parent::__construct($message, $code, $previous); } diff --git a/server/app/common/http/middleware/AllowMiddleware.php b/server/app/common/http/middleware/AllowMiddleware.php index 1d67c7d5ca61b3af9fa4c1d6d95eee7144b292d6..d4a1fc94b442a5bcb5b343df2f5f6aaa25041e4d 100644 --- a/server/app/common/http/middleware/AllowMiddleware.php +++ b/server/app/common/http/middleware/AllowMiddleware.php @@ -46,9 +46,12 @@ class AllowMiddleware implements MiddlewareInterface $response = response(''); }else{ $response = $handler($request); + //记录日志 try{ - $this->taskLog($request,$response); - }catch (\Exception|\Throwable $e){} + OperationLog::handle($request,$response); + }catch (\Exception|\Throwable $e){ + Log::error('请求日志记录失败:'.$e->getMessage()); + } } // 给响应添加跨域相关的http头 @@ -61,14 +64,4 @@ class AllowMiddleware implements MiddlewareInterface ]); return $response; } - public function taskLog($request,$response): bool - { - try{ - OperationLog::handle($request,$response); - }catch (\Exception $e){ - Log::info('请求日志记录失败:'.$e->getMessage()); - return false; - } - return true; - } } \ No newline at end of file diff --git a/server/app/common/http/middleware/EndMiddleware.php b/server/app/common/http/middleware/EndMiddleware.php index e1a4422c99dd95384d76bd5fed824a40336754ad..e78c7470dd88f7944a6769642e1351c5b6b3df3d 100644 --- a/server/app/common/http/middleware/EndMiddleware.php +++ b/server/app/common/http/middleware/EndMiddleware.php @@ -37,8 +37,9 @@ class EndMiddleware implements MiddlewareInterface public function process(Request $request, callable $handler): Response { + $controllerObject = make($request->controller); // 如果是opitons请求则返回一个空的响应,否则继续向洋葱芯穿越,并得到一个响应 - $request->controllerObject->initialize(); + $controllerObject->initialize(); return $handler($request); } diff --git a/server/app/common/service/JsonService.php b/server/app/common/service/JsonService.php index e0a2c98611e4806501042dbac73ee00614b0bdf6..db36136162c6e93c3f367bea5a3201f21bb8ffb1 100644 --- a/server/app/common/service/JsonService.php +++ b/server/app/common/service/JsonService.php @@ -15,66 +15,71 @@ class JsonService { /** * @notes 接口操作成功,返回信息 - * @param string $msg - * @param array $data - * @param int $code - * @param int $show + * @param string $msg 信息 + * @param array $data 数据 + * @param int $code 状态码 + * @param int $show 是否显示 + * @param int $httpStatus http状态码 + * @param int $options 可选 JSON_UNESCAPED_UNICODE json 格式化 * @author 乔峰 * @date 2021/12/24 18:28 */ - public static function success(string $msg = 'success', array $data = [], int $code = 1, int $show = 1) + public static function success(string $msg = 'success', array $data = [], int $code = 1, int $show = 1, int $httpStatus = 200,...$options): Response { - return self::result($code, $show, $msg, $data); + return self::result($code, $show, $msg, $data, $httpStatus,...$options); } /** * @notes 接口操作失败,返回信息 - * @param string $msg - * @param array $data - * @param int $code - * @param int $show + * @param string $msg 信息 + * @param array $data 数据 + * @param int $code 状态码 + * @param int $show 是否显示 + * @param int $httpStatus http状态码 + * @param int $options 可选 JSON_UNESCAPED_UNICODE json 格式化 * @author 乔峰 * @date 2021/12/24 18:28 */ - public static function fail(string $msg = 'fail', array $data = [], int $code = 0, int $show = 1) + public static function fail(string $msg = 'fail', array $data = [], int $code = 0, int $show = 1, int $httpStatus = 200,...$options): Response { - return self::result($code, $show, $msg, $data); + return self::result($code, $show, $msg, $data, $httpStatus,...$options); } /** * @notes 接口返回数据 - * @param $data + * @param array $data 数据 * @author 乔峰 * @date 2021/12/24 18:29 */ - public static function data($data) + public static function data(array $data): Response { return self::success('', $data, 1, 0); } /** * @notes 接口返回信息 - * @param int $code - * @param int $show - * @param string $msg - * @param array $data - * @param int $httpStatus + * @param int $code 状态码 + * @param int $show 是否显示 + * @param string $msg 信息 + * @param array $data 数据 + * @param int $httpStatus http状态码 + * @param int $options 可选 JSON_UNESCAPED_UNICODE json 格式化 * @author 乔峰 * @date 2021/12/24 18:29 */ - private static function result(int $code, int $show, string $msg = 'OK', array $data = [], int $httpStatus = 200) + private static function result(int $code, int $show, string $msg = 'OK', array $data = [], int $httpStatus = 200,...$options): Response { $result = compact('code', 'show', 'msg', 'data'); - return json($result, $httpStatus); + return json($result, $httpStatus,...$options); } /** * @notes 抛出异常json - * @param string $msg - * @param array $data - * @param int $code - * @param int $show + * @param string $msg 信息 + * @param array $data 数据 + * @param int $code 状态码 + * @param int $show 是否显示 * @author 乔峰 * @date 2021/12/24 18:29 */ @@ -86,11 +91,11 @@ class JsonService /** * @notes 数据列表 - * @param \app\common\lists\BaseDataLists $lists + * @param BaseDataLists $lists 数据列表 * @author 令狐冲 * @date 2021/7/28 11:15 */ - public static function dataLists(BaseDataLists $lists) + public static function dataLists(BaseDataLists $lists): Response { //获取导出信息 if ($lists->export == ExportEnum::INFO && $lists instanceof ListsExcelInterface) { diff --git a/server/app/crontab/Task.php b/server/app/crontab/Task.php index 8faf4ecd88afaf00c66a85881b217d9e8c32d22c..4d4d56e7432bf69d23af8cd9c590c3ee5a7c3278 100644 --- a/server/app/crontab/Task.php +++ b/server/app/crontab/Task.php @@ -38,6 +38,13 @@ class Task new Crontab('50 7 * * *', function(){ echo date('Y-m-d H:i:s')."\n"; }); + // 每天的2点30执行,注意这里省略了秒位 + new Crontab('30 2 * * *', function(){ + //todo 删除日志表日志 + \app\common\model\OperationLog::destroy(function ($query) { + $query->where('create_time','<',strtotime("-15 day")); + },true); + }); } } \ No newline at end of file diff --git a/server/config/log.php b/server/config/log.php index 75916bcaf63290d26c4f7e683d3fad70348c45ff..14e30c6541c1564567b64289c553555f29262790 100644 --- a/server/config/log.php +++ b/server/config/log.php @@ -11,37 +11,38 @@ * @link http://www.workerman.net/ * @license http://www.opensource.org/licenses/mit-license.php MIT License */ - +$handlers = [ + [ + 'class' => Monolog\Handler\RotatingFileHandler::class, + 'constructor' => [ + runtime_path() . '/logs/webman.log', + 7, //$maxFiles + Monolog\Logger::DEBUG, + ], + 'formatter' => [ + 'class' => Monolog\Formatter\LineFormatter::class, + 'constructor' => [null, 'Y-m-d H:i:s', true], + ], + ] +]; +if (getenv('APP_DEBUG',false)){ + /** + * 输出到控制台 + */ + $handlers[] = [ + 'class' => Monolog\Handler\StreamHandler::class, + 'constructor' => [ + 'php://stdout', + Monolog\Logger::DEBUG, + ], + 'formatter' => [ + 'class' => Monolog\Formatter\LineFormatter::class, + 'constructor' => [null, 'Y-m-d H:i:s', true], + ], + ]; +} return [ 'default' => [ - 'handlers' => [ - [ - 'class' => Monolog\Handler\RotatingFileHandler::class, - 'constructor' => [ - runtime_path() . '/logs/webman.log', - 7, //$maxFiles - Monolog\Logger::DEBUG, - ], - 'formatter' => [ - 'class' => Monolog\Formatter\LineFormatter::class, - 'constructor' => [null, 'Y-m-d H:i:s', true], - ], - ], - /** - * 输出到控制台 - */ - [ - 'class' => Monolog\Handler\StreamHandler::class, - 'constructor' => [ - 'php://stdout', - Monolog\Logger::DEBUG, - ], - 'formatter' => [ - 'class' => Monolog\Formatter\LineFormatter::class, - 'constructor' => [null, 'Y-m-d H:i:s', true], - ], - ] - - ], + 'handlers' => $handlers, ], ]; diff --git a/server/support/helpers.php b/server/support/helpers.php index 8de22c00cf64932eb56ccb15e9da4141d062e324..84600ceb1514c33c7bc9cdb1d01efe5f43c9ef56 100644 --- a/server/support/helpers.php +++ b/server/support/helpers.php @@ -130,18 +130,17 @@ function response(string $body = '', int $status = 200, array $headers = []): Re { return new Response($status, $headers, $body); } - /** * Json response * @param $data * @param int $options * @return Response */ -function json($data, int $options = JSON_UNESCAPED_UNICODE): Response +function json($data,$httpStatus, ... $options): Response { - return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options)); + $result = new Response($httpStatus, ['Content-Type' => 'application/json'], json_encode($data,...$options)); + return $result; } - /** * Xml response * @param $xml