登录框里输个奇怪的单引号,页面直接吐出数据库报错,这种反应说明后端八成在拼接 SQL 字符串。防止sql注入的思路就一句话:别让用户输入有机会被当成 SQL 语法执行。

问题出在哪

把账号密码直接拼进查询语句,输入里夹带单引号等字符时,拼出来的语句结构就变了,输入从数据变成了语句的一部分。参数化查询解决的正是这件事:语句结构先发给数据库预编译,数据后传进去,数据库只把它当数据处理,永远不会当命令解析。

参数化查询怎么写

PHP 的 PDO 写法:

$stmt = $pdo->prepare('select * from users where name = :name');
$stmt->execute(['name' => $name]);

Java 里对应 PreparedStatement,用问号占位再按顺序 set 值;Python 的 DB-API、Go 的 database/sql 都有同样的机制。多数 ORM 框架默认就走参数化,但要小心自己手写原生查询时绕过了它。

参数化之外的几道防线

  • 数据库账号给最小权限,业务账号别用 root,只读的账号就不给写权限
  • 按类型校验输入,数字字段强制转数字,长度和格式卡死
  • 详细报错只进日志,页面上只给友好提示
  • 用不到的数据库功能、存储过程权限直接关掉

靠过滤特殊字符只能算补救,转义规则总有覆盖不到的场景,别把它当唯一手段。防止sql注入真正省心的主线就一条:查询全部参数化,权限给到最小,日志里盯告警。老项目改造时优先把拼接查询挨个换掉,改动不大,收益最直接。