C#类库中安全执行SQL查询?NuGet包SQL代码防泄露方案
当前实现的核心问题
1. 线程安全隐患
ConnectionGetter类使用静态的MySqlConnection和MySqlCommand,当多个用户同时调用GetStuff时,会出现连接资源竞争,导致数据错乱或抛出异常,完全不适合多线程场景。
2. 连接管理错误
GetStuff的构造函数打开了数据库连接,但Dispose方法未实现关闭逻辑,会造成数据库连接泄漏,最终耗尽连接池资源。
3. SQL语句极易暴露
SQL查询硬编码在类的构造函数中,用户只需用反编译工具(如ILSpy、dnSpy)就能直接看到表名information、列名stuff,完全无法保护数据库结构隐私。
防止SQL查询暴露的安全方案
后端API中转(最安全彻底)
放弃让NuGet包直接连接数据库的方案,搭建一个后端Web API(如ASP.NET Core API),将数据库查询逻辑放在服务器端。NuGet包仅负责调用API接口获取数据,用户完全接触不到任何数据库相关信息,包括连接字符串、SQL语句、表结构。代码混淆
使用.NET代码混淆工具(如ConfuserEx、SmartAssembly)对编译后的NuGet包DLL进行混淆处理,混淆会打乱代码逻辑、加密字符串,让反编译后的SQL语句难以识别,大幅提高逆向成本。使用数据库存储过程
将查询逻辑封装为MySQL存储过程,NuGet包中仅调用存储过程名称,而非直接编写SQL。例如:-- 在数据库中创建存储过程 CREATE PROCEDURE GetStuffData() BEGIN SELECT stuff FROM information; END;NuGet包中的代码改为:
string _procCall = "CALL GetStuffData();"; using(var command = new MySqlCommand(_procCall, _con))用户只能看到存储过程名,无法得知底层的表和列信息。
加密SQL字符串
将SQL语句用AES等算法加密后,存储在NuGet包的资源文件或内嵌配置中,运行时再解密执行。虽然无法完全防止逆向,但比直接硬编码的隐私性更高。
基础实现修复(临时过渡方案)
如果暂时无法重构架构,先修复现有代码的致命问题:
public class GetStuff : IDisposable { public string? name; private MySqlConnection? _connection; public void Dispose() { // 确保连接被关闭和释放 _connection?.Close(); _connection?.Dispose(); } public GetStuff() { Console.WriteLine("Connecting to Server..."); string connString = System.Configuration.ConfigurationManager.ConnectionStrings["CONNECTIONSETUP"].ConnectionString; _connection = new MySqlConnection(connString); _connection.Open(); // 使用using自动释放资源 string query = "SELECT stuff FROM information;"; using(var command = new MySqlCommand(query, _connection)) using(var reader = command.ExecuteReader()) { if(reader.Read()) { name = reader.GetString(0); } } } }
- 移除静态的ConnectionGetter类,每次创建独立的数据库连接,避免线程冲突
- 使用
using语句自动释放Command和Reader资源 - 在Dispose方法中正确关闭并释放数据库连接
内容的提问来源于stack exchange,提问作者HenryCollin

