api.php 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. <?php
  2. /**
  3. * BCJD 导航 - RESTful API 接口
  4. *
  5. * 使用 OOP 类库重构,引入控制器模式。
  6. *
  7. * 端点:
  8. * GET ?action=get_links - 获取链接列表
  9. * POST ?action=login - 登录
  10. * POST ?action=logout - 退出
  11. * POST ?action=check_login - 检查登录状态
  12. * POST ?action=get_csrf - 获取 CSRF Token
  13. * POST ?action=add_link - 添加链接(需登录)
  14. * POST ?action=delete_link - 删除链接(需登录)
  15. * POST ?action=update_link - 更新链接(需登录)
  16. * POST ?action=update_password - 修改密码(需登录)
  17. */
  18. require_once __DIR__ . '/../init.php';
  19. use BCJD\Auth;
  20. use BCJD\LinkManager;
  21. use BCJD\Response;
  22. // ---- CORS 头 ----
  23. header('Access-Control-Allow-Origin: *');
  24. header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
  25. header('Access-Control-Allow-Headers: Content-Type, X-CSRF-Token');
  26. // 预检请求直接返回
  27. if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
  28. http_response_code(204);
  29. exit;
  30. }
  31. $action = $_GET['action'] ?? $_POST['action'] ?? '';
  32. $csrfToken = $_POST['csrf_token'] ?? $_SERVER['HTTP_X_CSRF_TOKEN'] ?? '';
  33. try {
  34. switch ($action) {
  35. // ===== 获取链接 =====
  36. case 'get_links':
  37. $lm = new LinkManager();
  38. Response::json([
  39. 'logged_in' => Auth::isLoggedIn(),
  40. 'groups' => $lm->getLinks(),
  41. ]);
  42. break;
  43. // ===== 登录 =====
  44. case 'login':
  45. $password = $_POST['password'] ?? '';
  46. if (empty($password)) {
  47. Response::error('请输入密码');
  48. }
  49. if (Auth::verifyPassword($password)) {
  50. Auth::login();
  51. Response::success(['message' => '登录成功']);
  52. } else {
  53. Response::error('密码错误', 401);
  54. }
  55. break;
  56. // ===== 退出 =====
  57. case 'logout':
  58. Auth::logout();
  59. Response::success(['message' => '已退出']);
  60. break;
  61. // ===== 检查登录状态 =====
  62. case 'check_login':
  63. Response::json(['logged_in' => Auth::isLoggedIn()]);
  64. break;
  65. // ===== 获取 CSRF Token =====
  66. case 'get_csrf':
  67. Auth::requireLogin();
  68. Response::json(['csrf_token' => Auth::getCsrfToken()]);
  69. break;
  70. // ===== 添加链接 =====
  71. case 'add_link':
  72. if (!Auth::validateCsrfToken($csrfToken)) {
  73. Response::error('CSRF 验证失败,请刷新页面重试', 403);
  74. }
  75. $lm = new LinkManager();
  76. $id = $lm->addLink($_POST);
  77. Response::success(['id' => $id]);
  78. break;
  79. // ===== 删除链接 =====
  80. case 'delete_link':
  81. if (!Auth::validateCsrfToken($csrfToken)) {
  82. Response::error('CSRF 验证失败,请刷新页面重试', 403);
  83. }
  84. $lm = new LinkManager();
  85. $lm->deleteLink((int)($_POST['id'] ?? 0));
  86. Response::success();
  87. break;
  88. // ===== 更新链接 =====
  89. case 'update_link':
  90. if (!Auth::validateCsrfToken($csrfToken)) {
  91. Response::error('CSRF 验证失败,请刷新页面重试', 403);
  92. }
  93. $lm = new LinkManager();
  94. $lm->updateLink((int)($_POST['id'] ?? 0), $_POST);
  95. Response::success();
  96. break;
  97. // ===== 修改密码 =====
  98. case 'update_password':
  99. if (!Auth::validateCsrfToken($csrfToken)) {
  100. Response::error('CSRF 验证失败,请刷新页面重试', 403);
  101. }
  102. LinkManager::updatePassword(
  103. $_POST['old_password'] ?? '',
  104. $_POST['new_password'] ?? '',
  105. $_POST['confirm_password'] ?? ''
  106. );
  107. Response::success(['message' => '密码已更新']);
  108. break;
  109. default:
  110. Response::error('未知操作: ' . $action, 400);
  111. }
  112. } catch (\PDOException $e) {
  113. // 生产环境不暴露数据库错误细节
  114. error_log('Database error: ' . $e->getMessage());
  115. Response::error('数据库操作失败,请稍后重试', 500);
  116. } catch (\Throwable $e) {
  117. error_log('Unexpected error: ' . $e->getMessage());
  118. Response::error('服务器内部错误', 500);
  119. }