如何在 Nginx 环境下使用 PHP 安全地写入 JSON 文件

1次阅读

如何在 Nginx 环境下使用 PHP 安全地写入 JSON 文件

本文详解在 nginx + php(如 raspberry pi 上的 php-fpm)环境中,通过表单提交动态更新 json 文件的完整实现方案,涵盖语法修正、文件权限配置、安全防护要点及错误处理技巧。

本文详解在 nginx + php(如 raspberry pi 上的 php-fpm)环境中,通过表单提交动态更新 json 文件的完整实现方案,涵盖语法修正、文件权限配置、安全防护要点及错误处理技巧。

在 Nginx 服务器上使用 PHP 写入 json 文件是一个常见但易出错的操作——尤其当页面提交后跳转至空白页、JSON 文件未更新或出现 500 internal Server Error 时,问题往往源于语法错误、路径权限不足、PHP 配置限制或逻辑缺陷。以下是一套经过验证的、生产就绪的实现方案。

✅ 核心修复与最佳实践

首先,原始代码中存在一个致命语法错误:

'name'=>>$_POST['username']  // ❌ 多了一个 >

应修正为:

'name' => $_POST['username']  // ✅ 正确的数组键值语法

其次,避免将 HTML 表单与处理逻辑分离在 index.html 和 index.php 中——这不仅导致路由混乱(如 action=”index.php” 提交后覆盖首页),还容易引发 Nginx 的静态文件优先匹配问题(.html 不经 PHP 解析)。推荐采用「单文件混合模式」:HTML 前端与 PHP 后端逻辑统一置于 index.php 中,由同一入口响应 GET(展示表单)和 POST(处理数据)请求。

立即学习PHP免费学习笔记(深入)”;

✅ 完整可运行示例(index.php)

<?php $output = null; $filepath = 'whitelist.json';  // 仅在表单提交且字段非空时执行写入 if ($_SERVER['REQUEST_METHOD'] === 'POST' &&      isset($_POST['submit']) &&      !empty(trim($_POST['uuid'])) &&      !empty(trim($_POST['username']))) {      // 1. 初始化数据:若 JSON 文件不存在,则创建空数组     if (file_exists($filepath)) {         $json_content = file_get_contents($filepath);         $json_arr = json_decode($json_content, true);         if (json_last_error() !== JSON_ERROR_NONE) {             $output = "⚠️ JSON 文件格式损坏,请手动检查或删除后重试。";         }     } else {         $json_arr = [];     }      // 2. 安全过滤输入(防止 XSS 或恶意字符注入)     $safe_uuid   = filter_var($_POST['uuid'], FILTER_SANITIZE_STRING);     $safe_name   = filter_var($_POST['username'], FILTER_SANITIZE_STRING);      // 3. 追加新条目(注意:此处不校验 UUID 重复性,如需请自行扩展)     $json_arr[] = [         'uuid' => $safe_uuid,         'name' => $safe_name,         'timestamp' => date('c') // 可选:记录写入时间     ];      // 4. 原子化写入:先写入临时文件,再原子替换,避免并发写入损坏     $temp_file = $filepath . '.tmp';     $json_encoded = json_encode($json_arr, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);      if (file_put_contents($temp_file, $json_encoded) !== false) {         if (rename($temp_file, $filepath)) {             $output = "✅ 成功写入!共 " . count($json_arr) . " 条记录,已保存至 <code>{$filepath}</code>。";         } else {             $output = "❌ 无法重命名临时文件,请检查目录写入权限。";         }     } else {         $output = "❌ JSON 编码失败或磁盘空间不足。";     } } ?>  <!DOCTYPE html> <html lang="zh-CN"> <head>     <meta charset="UTF-8">     <title>白名单管理</title>     <style>         body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; margin: 4rem auto; max-width: 600px; padding: 0 1rem; }         .group { margin: 1rem 0; }         input[type="text"] { width: 100%; padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px; }         button { background: #007bff; color: white; border: none; padding: 0.75rem 1.5rem; border-radius: 4px; cursor: pointer; }         .message { margin-top: 1rem; padding: 0.5rem; border-radius: 4px; }         .success { background: #d4edda; color: #155724; border: 1px solid #c3e6cb; }         .error { background: #f8d7da; color: #721c24; border: 1px solid #f5c6cb; }     </style> </head> <body>     <h1>? 白名单添加</h1>      <form method="POST" autocomplete="off">         <div class="group">             <input type="text" name="uuid" placeholder="请输入 UUID(如:123e4567-e89b-12d3-a456-426614174000)" required>         </div>         <div class="group">             <input type="text" name="username" placeholder="请输入用户名" required>         </div>         <button type="submit" name="submit">提交</button>     </form>      <?php if ($output): ?>         <div class="message <?= strpos($output, '✅') !== false ? 'success' : 'error' ?>">             <?= htmlspecialchars($output) ?>         </div>     <?php endif; ?>      <!-- 可选:显示当前 JSON 内容摘要 -->     <?php if (file_exists($filepath)): ?>         <details style="margin-top: 1.5rem;">             <summary>? 当前白名单(仅显示前 5 条)</summary>             <pre class="brush:php;toolbar:false;" style="max-height: 200px; overflow: auto; background: #f5f5f5; padding: 0.5rem; border-radius: 4px; font-size: 0.9em;"> <?php $json_preview = json_decode(file_get_contents($filepath), true); $preview = array_slice($json_preview ?? [], 0, 5); echo json_encode($preview, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); ?>

text=ZqhQzanResources