1. 数据验证 – 永远不要信任你的用户
来自用户输入或其他系统的数据,你都必须要进行验证。否则,这会对当前系统造成威胁,并导致不可想象的安全漏洞。现在,让我们学习如何验证Node.js中的传入数据。你可以使用名为 validator 的模块来执行数据验证。 例如:
- const validator = require('validator');
- validator.isEmail('foo@bar.com'); //=> true
- validator.isEmail('bar.com'); //=> false
另外,你也可以使用 joi 模块来进行数据和模型的验证,例如:
- const joi = require('joi');
- try {
- const schema = joi.object().keys({
- name: joi.string().min(3).max(45).required(),
- email: joi.string().email().required(),
- password: joi.string().min(6).max(20).required()
- });
- const dataToValidate = {
- name: "Shahid",
- email: "abc.com",
- password: "123456",
- }
- const result = schema.validate(dataToValidate);
- if (result.error) {
- throw result.error.details[0].message;
- }
- } catch (e) {
- console.log(e);
- }
2. SQL注入攻击
SQL注入可以让恶意用户通过传递非法参数,来篡改SQL语句。下面是一个例子,假设你写了这样一个SQL:
- UPDATE users
- SET first_name="' + req.body.first_name + '" WHERE id=1332;
在正常情况下,你希望这次查询应该是这样的:
- UPDATE users
- SET first_name = "John" WHERE id = 1332;
但是现在,如果有人将 first_name 的值按下面这种方式传递:
- John", last_name="Wick"; —
这时,你的SQL语句就会变成这样:
- UPDATE users
- SET first_name="John", last_name="Wick"; –" WHERE id=1001;
你会看到, WHERE 条件被注释掉了,这次更新会将整张表所有用户的 first_name 改成 John , last_name 改成 Wick 。这下,你闯祸了!
如何避免SQL注入
避免SQL注入攻击最有效的办法就是将输入数据进行过滤。你可以对每一个输入数据逐一进行验证,也可以用参数绑定的方式验证。开发者们最常用的就是参数绑定的方式,因为它高效而且安全。
如果你在使用一些比较流行的ORM框架,例如sequelize、hibernate等等,那么框架中就已经提供了这种数据验证和SQL注入保护机制。
如果你更喜欢依赖数据库模块,例如 mysql for Node ,那么你可以使用数据库提供的过滤方法。下面代码是使用 mysql for Node 的一个例子:
- var mysql = require('mysql');
- var connection = mysql.createConnection({
- host : 'localhost',
- user : 'me',
- password : 'secret',
- database : 'my_db'
- });
- connection.connect();
- connection.query(
- 'UPDATE users SET ?? = ? WHERE ?? = ?',
- ['first_name',req.body.first_name, ,'id',1001],
- function(err, result) {
- //…
- });
?? 的地方被字段名称替换, ? 的地方被字段值替换,这样就保证了输入值的安全性。
你也可以使用存储过程来提高安全级别,但是由于缺乏可维护性,开发人员倾向于避免使用存储过程。
同时,你还应该执行服务器端的数据验证。 但我不建议你手动验证每个字段,可以使用 joi 等模块来解决这个问题。