最有效的方式是使用参数化查询防止SQL注入。通过占位符区分代码与数据,如pymysql中cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,));表名等结构元素需白名单校验;辅以最小权限、错误信息隐藏等措施。

最有效的方式是使用参数化查询(预编译语句),而不是拼接 SQL 字符串。
用参数化查询代替字符串拼接
直接把用户输入拼进 SQL 里,比如 red">"SELECT * FROM users WHERE name = '" + name + "'",是高危操作。数据库会把拼进去的内容当作 SQL 代码执行,攻击者可以输入 ' OR '1'='1 来绕过验证。
正确做法是使用占位符,让数据库区分“代码”和“数据”:
- MySQL(Python + pymysql):cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))
- PostgreSQL(Python + psycopg2):cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))
- Java(JDBC):PreparedStatement stmt = conn.prepareStatement("SELECT * FROM users WHERE id = ?"); stmt.setInt(1, userId);
避免动态拼接表名、列名等结构元素
参数化查询只能防止值(value)被注入,不能用于表名、列名、排序字段、LIMIT 数值等语法结构部分。这些必须通过白名单严格控制:
该系统采用多层模式开发,这个网站主要展示女装的经营,更易于网站的扩展和后期的维护,同时也根据常用的SQL注入手段做出相应的防御以提高网站的安全性,本网站实现了购物车,产品订单管理,产品展示,等等,后台实现了动态权限的管理,客户管理,订单管理以及商品管理等等,前台页面设计精致,后台便于操作等。实现了无限子类的添加,实现了动态权限的管理,支持一下一个人做的辛苦
- 排序字段:只允许 ['name', 'age', 'created_at'] 中的值,校验后再拼接
- 分页数量:LIMIT 后的数字必须转为整数并做范围检查(如 ≤ 100)
- 表名/列名:不接受任何外部输入,或从预定义字典中映射(如 {'u': 'users', 'p': 'products'})
其他辅助防护手段
参数化是核心,但配合以下措施更稳妥:
- 最小权限原则:应用数据库账号只给必要权限(如仅 SELECT/INSERT,禁用 DROP、EXECUTE)
- 错误信息不暴露细节:生产环境关闭数据库原始报错(如 “MySQL syntax error”),避免泄露表结构
- 输入格式校验:邮箱、手机号、数字 ID 等字段,在进入 SQL 前就用正则或类型转换过滤异常内容
- 使用 ORM 时仍需谨慎:Django 的 filter(name=input) 是安全的,但 extra(where=[...]) 或原生 SQL 调用仍可能引入风险
不复杂但容易忽略:只要所有用户可控的数据都走参数绑定,SQL 注入基本就防住了。关键不是“有没有过滤”,而是“有没有让数据库明确知道哪部分是数据”。









