前言:零点博客的折腾之路

最近在零点博客维护一套CMS时,为了方便给不同客户导出数据,我决定自己写一个在线JSON转SQL的工具。听起来挺简单,但真干起来发现坑不少。尤其是涉及到SQL语句的拼接和数据库交互时,安全性是第一位的。今天就来复盘一下这个过程,从后端C#解析到前端HTML展示,再到核心的SQL语句编写,咱们一步步来。

一、 后端架构:C#与MySQL的对接

这工具的后端我选用了熟悉的C# (.NET Core)。主要流程就是:接收前端传来的JSON数据 -> 解析 -> 验证 -> 拼接成SQL语句 -> 执行。

咱们先看怎么把JSON转成List对象,这里用到了Json.NET库:

// 简单的实体映射
var jsonStr = "{\"id\":1,\"name\":\"测试\"}";
var obj = JsonConvert.DeserializeObject<MyModel>(jsonStr);

拿到数据后,就是最关键的一步:如何把数据变成可执行的SQL语句?

二、 核心痛点:正则与SQL语句拼接

在拼接SQL语句前,必须做数据清洗。很多非结构化数据里会有特殊字符,比如引号、分号,这会直接导致SQL报错或更严重的注入问题。

我写了一个简单的正则表达式来清洗字符串:

string CleanSql(string input)
{
    // 将单引号转义,防止SQL语法错误
    return Regex.Replace(input, @"'", "''");
}

清洗完数据后,我开始组装SQL语句。最基础的做法是用字符串拼接:

string sql = $"INSERT INTO users (name, age) VALUES ('{CleanSql(user.Name)}', {user.Age})";

但是,这种写法在SQL注入攻击面前就像纸糊的一样。为了演示效果,大家可以测试一下这个漏洞:

// 输入: 123' OR '1'='1
// 注入后的SQL语句会变成:
// INSERT INTO users (name, age) VALUES ('123' OR '1'='1', ...)

三、 避坑指南:预处理语句与参数化查询

为了避免这种隐患,我们必须抛弃字符串拼接,改用SQL注入防护。在C#连接MySQL时,使用预处理语句是标准做法。

修改后的代码如下,重点在于将参数与SQL结构分离:

// 使用 MySqlCommand 和 参数化查询
string sql = "INSERT INTO users (name, age) VALUES (@name, @age)";

using (var conn = new MySqlConnection(connString))
{
    conn.Open();
    using (var cmd = new MySqlCommand(sql, conn))
    {
        // 绑定参数,数据库会自动处理转义
        cmd.Parameters.AddWithValue("@name", CleanSql(user.Name));
        cmd.Parameters.AddWithValue("@age", user.Age);

        int rows = cmd.ExecuteNonQuery();
        Console.WriteLine($"执行成功,影响行数: {rows}");
    }
}

你会发现,无论输入什么特殊的字符串,数据库都会把它当作普通文本处理,而不是可执行的代码。这就是SQL语句安全的根本。

四、 前端交互:JS解析JSON与反馈

工具做好后,前端负责把JSON发给后端。这里前端用原生JS解析JSON非常快:

// 模拟发送请求
fetch('/api/convert-to-sql', {
    method: 'POST',
    body: JSON.stringify(jsonData)
});

后端返回生成的SQL语句,前端再用正则高亮显示,让用户复制。

五、 总结与复盘

开发这个工具最大的收获就是深刻理解了SQL语句的生命周期:从字符串拼接的风险,到预处理语句的救赎。

  • 对于普通开发,尽量少用字符串拼接写SQL语句。
  • 对于数据库操作,永远使用参数化查询。
  • 在写爬虫或接口时,输入数据的清洗至关重要。

如果你在开发EMLOG插件或自定义CMS时遇到类似的坑,欢迎在零点博客留言交流。希望这份复盘对大家有帮助!