编程全栈开发员

谈谈参数化查询和动态 SQL。何时使用每种方法,动态 SQL 存在什么风险,以及如何避免这些风险?举例说明。

用 Hintsage AI 助手通过面试

答复。

参数化查询允许通过特殊参数而不是直接通过变量替换的方式将值传递到查询中。这增强了安全性,防止 SQL 注入,同时通过计划缓存加快了重复查询的执行。

动态 SQL 允许实时构建和执行查询(例如,使用 MS SQL 中的 EXEC sp_executesql 或 PostgreSQL 中的 PREPARE/EXECUTE)。必须非常小心:直接在查询文本中插入值可能导致 SQL 注入、语法错误和性能不佳。

参数化查询示例(使用 psycopg2 库的 Python):

cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))

PostgreSQL 中的动态 SQL 示例:

EXECUTE format('SELECT * FROM %I WHERE value = %L', tablename, value);

陷阱问题。

问题: 为什么简单地转义引号(')如某些旧应用程序所做的方式不足以防止 SQL 注入?

回答:

转义引号无法保护所有类型的注入,尤其是当攻击者插入 SQL 查询结构(例如,"; DROP TABLE users;")时。此外,它并不涵盖不同数据类型的所有特性,也无法防止通过编码或特殊字符绕过过滤器。始终应使用参数化查询。


故事

在某薪资计算系统中,动态 SQL 生成报告。由于旧框架不支持参数化,手动拼接字符串。一位用户偶然(或不太偶然)在“姓”字段中传入 SQL 片段,这使得他获得了其他人的薪资。

故事

一家小型在线商店使用动态 SQL 进行商品过滤,但没有进行适当的验证。当用户试图指定非标准值时,引发了 SQL 解析器错误,使得所有商品的展示暂时“瘫痪”。

故事

在 CRM 中,字母“O'Connor”在构建 SQL 查询时导致应用程序错误,因字符串简单拼接而未转义的单引号使得任何带有此姓氏的条目都无法保存,这一问题直到一年后才被发现。