'preliminary']); // 登录 + 模块权限(写接口另含 Ajax/CSRF) * $pdo = Api::boot(); // 仅要求登录(如 session.php) * $pdo = Api::boot(['super' => true]); // 仅超级管理员 * $pdo = Api::boot(['permissions' => [...]]); // 任一权限 * $pdo = Api::boot(['public' => true]); // 免登录(仅 login/forgot/csrf) * * boot() 统一执行: * - 安全 Session(httponly/samesite) * - POST/PUT/PATCH/DELETE:checkAjax(X-Requested-With)+ checkCsrf(Token 头) * - 登录态 + 权限 * - 返回 PDO(后续代码可直接用 $pdo;原 `$pdo = DB::getInstance()->getPdo();` * 属冗余无害,可保留) * * 本文件另注册全局异常处理器:未捕获异常统一转 JSON 500 + 技术日志。 */ require_once __DIR__ . '/db.php'; require_once __DIR__ . '/response.php'; require_once __DIR__ . '/logger.php'; require_once __DIR__ . '/security.php'; require_once __DIR__ . '/auth.php'; require_once __DIR__ . '/helpers.php'; require_once __DIR__ . '/validate.php'; require_once __DIR__ . '/duplicate_check.php'; require_once __DIR__ . '/completeness.php'; /** 统一异常处理:未捕获异常 → JSON 500 + 技术日志(REV-ARCH-3) */ set_exception_handler(function (\Throwable $e) { logError('未捕获异常', [ 'msg' => $e->getMessage(), 'file' => $e->getFile(), 'line' => $e->getLine(), 'uri' => $_SERVER['REQUEST_URI'] ?? '', ]); if (!headers_sent()) { http_response_code(500); header('Content-Type: application/json; charset=utf-8'); } echo json_encode(['code' => 500, 'msg' => '服务器内部错误,请稍后重试'], JSON_UNESCAPED_UNICODE); exit; }); class Api { /** * 统一引导 * @param array $opts 见文件头注释 * @return PDO */ public static function boot(array $opts = []) { startSessionSecure(); $isWrite = in_array($_SERVER['REQUEST_METHOD'] ?? 'GET', ['POST', 'PUT', 'PATCH', 'DELETE'], true); if ($isWrite) { checkAjax(); } if (empty($opts['public'])) { if (!empty($opts['super'])) { requireSuperAdmin(); } elseif (!empty($opts['module'])) { checkPermission($opts['module']); } elseif (!empty($opts['permissions'])) { checkAnyPermission($opts['permissions']); } else { requireLogin(); } } if ($isWrite) { checkCsrf(); } return DB::getInstance()->getPdo(); } }