一、背景
现象:直接使用普通的mysql select查询的时候,模糊匹配某些字段的时候,比如单引号',颜文字会出现报错,会出现语法错误的提示。
原因:是因为写了不正确的sql语句更改了查询的性质,这就是常见的 SQL 注入问题。
分析:对于特殊字符怎么能够sql查询正确呢?怎么减少 SQL 注入的风险?
二、方法
如果在 MySQL 中执行 SELECT SQL 查询时遇到导致语法不规范的字符,你可以尝试以下方法进行查询:
1、引号包裹字符串(一般不是这个问题)
如果查询中包含字符串,确保字符串被正确地引号包裹。在 MySQL 中,可以使用单引号或双引号将字符串括起来,例如:SELECT * FROM table WHERE name = 'John'。
2、客户端预处理语句(参数化查询 PreparedStatement)
在MySQL中,客户端预处理语句是一种在应用程序和MySQL服务器之间进行的通信协议,该协议可以在执行查询之前将查询参数发送到MySQL服务器。
客户端预处理语句通过以下两种方式实现:
- 客户端将SQL查询语句发送给MySQL服务器。
- MySQL服务器根据查询中的占位符将查询参数发送回客户端。
在执行查询之前,客户端将使用查询参数替换查询中的占位符。
客户端预处理语句的主要优点是可以大大提高应用程序的性能。因为在执行查询之前,查询参数已经预处理,并且MySQL服务器已经准备好接收这些参数。
参数化查询是主要解决 SQL 注入的问题,这种方法通过将变量作为参数传递到 SQL 语句中,而不直接将其值与 SQL 语句连接起来,从而防止 SQL 注入攻击。
在执行查询时,MySQL 驱动会自动处理参数的转义,确保输入的值被正确地转义并安全地插入到查询语句中。
const mysql = require('mysql');
// 创建数据库连接
const connection = mysql.createConnection({
host: 'localhost',
user: 'your_username',
password: 'your_password',
database: 'your_database'
});
// 执行预处理语句
const sql = 'SELECT * FROM users WHERE username = ? AND password = ?';
const values = ['admin', 'password123'];
connection.query(sql, values, function (error, results, fields) {
if (error) throw error;
console.log(results);
});
// 关闭数据库连接
connection.end();
使用场景:如果查询中的数据来自用户输入或其他动态来源,最好使用预处理语句来执行查询。预处理语句可以防止 SQL 注入攻击,并自动处理特殊字符的转义。如果你调用的api只能传递完整的sql,那这个方法就不适用了。
3、转义特殊字符(部分防止 SQL 注入)
在构建 SQL 查询时,对输入的字符串进行转义处理,以确保特殊字符被正确地转义。这可以防止恶意输入破坏 SQL 查询语句的结构。
特殊字符:如单引号(')、双引号(")和反斜杠(\),需要使用反斜杠(\)进行转义。
转义封装方法:
- \
- mysql内置函数
- 正则表达式替换
4、输入验证和过滤(限制只能输入某些字符)
在构建 SQL 查询之前,对用户输入进行验证和过滤(前端表单,接口api)。确保只允许预期的字符和格式,并排除可能引起问题的特殊字符。
// 支持中文,英文大小写,数字,-_()()字符
const SQL_REGEXP =/^[\u4e00-\u9fa5a-zA-Z0-9-_()()]+$/
5、检查错误消息
如果查询语法错误,MySQL 数据库通常会返回相应的错误消息,其中可能包含有关错误的更多详细信息。检查错误消息以了解出现问题的具体部分,并进行相应的修正。为了安全性,可以自定义处理异常信息的方法返回,查询错误信息可以不要返回给用户, 将错误记录到日志中。
三、验证
使用上述方法进行开发后,可以使用正则表达式或其他验证方法来验证输入的有效性。