当前位置: 首页 > news >正文

npm mysql 注入_在 Node.js 中使用 MySQL MySQL JavaScript 客户端

NoSQL 数据库最近一段时间都是很受追捧的,也许已经是 Node.js 应用程序的首选后端了。不过,你不应该只是根据潮流来选择拿什么技术构建下一个项目,使用什么数据库类型要取决于项目的特定需求。如果你的项目涉及到动态表的创建,实时的插入等等,那么 NoSQL 就是不错的技术路线,而另一方面,如果项目中要处理复杂的查询和事务,那么 SQL 数据库就更加合适了。

在本教程中,我们会向你介绍如何使用MySQL 模块- 这是一个用 JavaScript 编写的运行在 Node.js 之上的 MySQL 驱动程序。我会向你解释如何使用该模块连接到 MySQL 数据库,执行常规的 CRUD 操作,之后就是对存储的过程进行检查,以及对用户的输入进行转义这些技术。这个颇受欢迎的教程在 2017 年 11 月 07 日进行了更新。其中的修改包括将语法更新到了 ES6,解决了node-mysql 模块被重新命名的问题,增加了更多对初学者友好的文字说明,并在 ORM 上新增加了一个部分。

106875172_1 快速入门:如何在Node 中使用MySQL

106875172_2

也许你来这是就是为了找到一个快速的法门。如果你是想用尽可能少的时间在 Node 中启动并运行 MySQL,我们能满足你的需求!

以下5个简单步骤告诉你如何在 Node 中使用 MySQL:创建一个新项目:mkdir mysql-test && cd mysql-test

创建一个 package.json 文件:npm init -y

安装mysql模块: npm install mysql –save

创建一个app.js文件并将下面的代码段复制进去。

运行该文件: node app.js。会看到一条 “Connected!”(已连接上了)消息。

106875172_3

106875172_1 安装 mysql 模块

106875172_2

现在让我们细化到第一步。首先,我们使用命令行创建一个新目录进进入这个目录。然后我们使用 npm init -y 命令创建 package.json 文件。-y 参数表示 npm 会使用默认值而不会问你各种问题。

这一步假设你已经在系统上安装了 Node 和 npm。如果还没安装,请阅读 SitePoint 上的这篇文章,它会指导你:使用 nvm 安装 Node.js 的多个版本。

然后,我们从 npm 安装mysql 模块并将其保存为项目的依赖项。项目的 dependencies (相对于 dev-dependencies) 是运行程序所需要的包。你可以阅读了解两者的区别。

106875172_4

如果你深入学习使用 npm,可以阅读这个指南,或者在我们的论坛上提问。

106875172_1 入门

106875172_2

在我们连接到数据库之前,有一件重要的事情就是要在你的机器上安装和配置 MySQL。如果这件事情还没做完,那就看看软件主页上的安装说明自己去装一个吧。

接下来我们需要做的就是创建一个数据库和一个数据库表。你可以使用一个图形用户界面来做到这一点,比如说phpMyAdmin,或者就使用命令行。 对于我们这篇文章,使用的是一个名为 sitepoint 的数据库和一个名为 employees 的表。如果你希望跟着一起操作的话,这里有一个数据库的转储文件,方便你可以快速地启动并运行起来:

106875172_5

106875172_6

106875172_1 连接到数据库

106875172_2

现在,我们在 mysql-test 目录下创建一个名为 app.js 的文件,来看看如何从 Node.js 连接到 MySQL。

106875172_7

现在打开一个终端并输入 node app.js。在连接成功建立之后,你应该能够在控制台中看到“Connection established”(连接已经建立好了)这条消息了。 如果出现了什么问题(例如输入了错误的密码),程序就会触发一个回调,该事件会传递出一个 JavaScript Error 对象(err)的实例。 你可以尝试将其打印到控制台以查看其中包含的有用信息以调试程序。

使用 Grunt 来监视文件的更改

每当我们对代码进行更改时,手动运行 node app.js 命令会变得有点乏味,所以让我们来把这个操作自动化吧。 这一节并不需要跟本教程的其余部分并没有依赖关系,不过如果照着做的话肯定会为你节省一些麻烦事儿。

我们首先得安装几个包:

106875172_8

Grunt是有名的 JavaScript 任务执行程序,每当监听到有文件发生修改时,grunt-contrib-watch都会运行已经预定义好的任务,并且会使用grunt-execute来运行 node app.js 命令。

安装完成之后,在项目根中创建一个名为Gruntfile.js的文件,然后在里面添加上如下代码。

106875172_9

现在运行 grunt watch 然后修改一下 app.js 文件。Grunt 就应该会检测到我们修改了文件并重新运行 node app.js 命令。

106875172_1 执行查询

106875172_2

读取

现在你知道如何在 Node.js 中建立 MySQL 连接了,再来看看如何执行 SQL 查询。我们从这里开始:建立使用 createConnection 命令连接到名为 sitepoint 的数据库。

106875172_10

连接建立后我们要使用连接变量来对数据库中的 employees 表进行查询。

106875172_11

现在运行 app.js (通过 grunt-watch 或者在终端输入 node app.js),你可以看到终端输出从数据库返回的数据。

106875172_12

从 MySQL 数据库返回的数据可以通过遍历 rows 对象来进行解析。

106875172_13

创建

你可以在数据库中执行 insert 查询,像这样:

106875172_14

请注意到我们是如何通过回调参数来获得刚插入那条记录的 ID 的。

更新

类似地,在执行 update 查询的时候,通过 result.affectedRows 可得到受影响的行数:

106875172_15

删除

delete 查询的操作也差不多:

106875172_16

106875172_1 高级用法

106875172_2

我希望有办法通过 mysql 模块来处理存储过程,以及转义用户输入。

存储过程

简单的说,存储过程是存储在数据库中,可以由数据库引擎和连接上数据的程序语言调用的程序(例如,SQL 程序)。如果你需要复习,请看看这篇不错的文章。

先来为我们的 sitepoint 数据库创建一个存储过程,它用于获取所有员工的详情。我们把它命名为 sp_getall。为了做这件事,你需要某种数据库接操作界面。我使用phpMyAdmin。在 sitepoint 数据库中运行下面的查询:

106875172_17

它会将程序保存在 information_schema 数据库的 ROUTINGS 表中。

106875172_18

下一步,建立连接并使用连接对象调用存储过程,像这样:

106875172_19

保存修改并运行。运行的时候你可以看到从数据库返回的数据。

106875172_20

这些数据包括一些附加信息,比如影响的行数,insertId 等。你需要对返回数据的第 0 个元素进行遍历以获取员工详情信息。

106875172_21

现在考虑一个需要输入参数的存储过程。

106875172_22

我们可以在调用存储过程的时候传入参数:

106875172_23

多数时候,如果我们想在数据库中插入一条记录,需要将插入记录的 ID 作为输出参数返回出来。考虑接下来用于插入数据的存储过程,它有一个输出参数:

106875172_24

为了调用含有输出参数的存储过程,我们需要在创建连接时调用多个程序。因此,修改连接,设置执行多个语句为 true。

106875172_25

然后在调用存储过程的时候,设置并传入一个输出参数。

106875172_26

在上面的代码中,我们设置了输出参数 @employee_id 并在调用存储过程的时候将其传入。一旦调用完成,我们需要使用 select 查询输出参数来获取返回的 ID。

运行 app.js。如果执行成功你可以看到 select 查询的输出参数和各种其它信息。通过 rows[2] 可获得输出参数的值。

106875172_27

转义用户输入

为了避免 SQL 注入攻击,你应该总是转义来自用户的任何数据,然后再把它用于 SQL 查询。来演示一下为什么:

106875172_28

这看起来并没有什么问题,它会返回正确的结果:

106875172_29

不过,如果我们将 userLandVariable 改为:

106875172_30

居然访问了整个数据集。如果我们再改为这样:

106875172_31

这下麻烦大了!

好消息是有办法处理这类问题。你只需要使用mysql.escape方法:

106875172_32或者使用问号占位符,就像我们在文章一开始提到的那个示例一样:

106875172_33

106875172_1 为什么不简单地使用 ORM?

106875172_2

你可能注意到了,评论中有人建议使用 ORM。在详述这个方法的优缺点之前,我先看看 ORM 是什么。下面是来自 Stack Overflow 的回答。对象关系映射(Object-Relational Mapping, ORM) 是一种允许人们使用面向对象范型来查询和操作数据库数据的技术。在谈到 ORM 的时候,多数人是指实现了 ORM 技术的某个库,所以会使用 “an ORM” 这样的短语。

因此,这种方法基本上意味着你会使用 ORM 领域相关的语言来编写数据库逻辑,而不是我们一直在讨论的普通方法。下面以Sequelize为例:

106875172_34

对比:

106875172_35

使用 ORM 对你是否有意义,取决于很多与你工作相关的因素,比如你在做什么以及为谁做。一方面,ORM 的形式使开发更为高效,从某种程序上来说,它抽象了大部分的 SQL 因而不需要团队中的每个人都去了解如何编写高效的数据库查询。它也很容易迁移到不同的数据库软件,因为你是在抽象层次上进行开发。

然而,从另一方面来说,由于不理解 ORM 是如何做的,所以可能会编写出一些混乱和低效的 SQL。性能也会是一个大问题,毕竟优化不通过 ORM 的查询要容易得多。

到底采用哪一种方法,决定权在你,但是如果正在做这个决定,请看看这个 Stack Overflow 的帖子:为什么应该使用 ORM?,以及 SitePoint 上的:你可能不知道的 3 个 JavaScript ORM。

106875172_1 小结

106875172_2

本教程中只涉及到了 MySQL 客户端的皮毛。我推荐你去阅读官方文档以了解更详细的信息。当然也有别的选择,比如node-mysql2和node-mysql-libmysqlclient。

你是否已经在 Node.js 中用过这些库来连接到 MySQL?我很想听人说说这些库。请在下面的评论中告诉我们你的想法、建议以及更正意见!

106875172_36更多干货请前往公众号菜单栏“戳我”->“干货分享”查看。

106875172_37

相关文章:

  • mysql 仇和_1008 数组元素循环右移问题 (20 分)
  • vc6 ado mysql_关于vc++6.0中 通过ADO连接数据库的问题!!
  • java读取文件路径_Java获取当前路径和读取文件
  • mongodb java group_在Java中实现MongoDB的Group功能
  • java获取用户地理位置_Java获取用户访问IP及地理位置的方法详解
  • java 部署tomcat_JavaWeb之Tomcat的安装和部署
  • java dump heap_java程序性能分析之thread dump和heap dump
  • java main命令行参数_关于java的main主入口方法的args字符串数组参数如何使用及命令行模拟实现...
  • java友元类_C++友元(Friend)用法实例简介
  • java form array_Java中数组操作 java.util.Arrays 类常用方法的使用
  • java类名的作用_java下Class.forName的作用是什么,为什么要使用它?
  • Java同步问题_Java中的同步问题
  • ubuntu php 编译安装mysql_ubuntu 8.04 编译安装 php mysql apache
  • java 构造器 this_Java 类的构造器中this()和super()的困惑
  • java为什么输入else错误_java – 我遇到了一个错误问题,我正在使用“else if”语句....
  • 【刷算法】求1+2+3+...+n
  • 【腾讯Bugly干货分享】从0到1打造直播 App
  • Linux链接文件
  • Lucene解析 - 基本概念
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • PhantomJS 安装
  • Python 基础起步 (十) 什么叫函数?
  • SQLServer插入数据
  • Swift 中的尾递归和蹦床
  • Theano - 导数
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 搭建gitbook 和 访问权限认证
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 机器人定位导航技术 激光SLAM与视觉SLAM谁更胜一筹?
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 微信公众号开发小记——5.python微信红包
  • 微信开源mars源码分析1—上层samples分析
  • 小程序 setData 学问多
  • 正则与JS中的正则
  • 2017年360最后一道编程题
  • FaaS 的简单实践
  • 阿里云移动端播放器高级功能介绍
  • 我们雇佣了一只大猴子...
  • ​VRRP 虚拟路由冗余协议(华为)
  • ​无人机石油管道巡检方案新亮点:灵活准确又高效
  • #1015 : KMP算法
  • #etcd#安装时出错
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • #LLM入门|Prompt#1.8_聊天机器人_Chatbot
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (function(){})()的分步解析
  • (附源码)spring boot儿童教育管理系统 毕业设计 281442
  • (附源码)计算机毕业设计SSM疫情社区管理系统
  • (一)使用Mybatis实现在student数据库中插入一个学生信息
  • (转) ns2/nam与nam实现相关的文件
  • .bat批处理(四):路径相关%cd%和%~dp0的区别
  • .NET 5.0正式发布,有什么功能特性(翻译)
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .NET 同步与异步 之 原子操作和自旋锁(Interlocked、SpinLock)(九)
  • .NET的微型Web框架 Nancy