NodeJs基础教程

需要笔记的可以以下链接获取:
Nodejs详细学习笔记
在这里插入图片描述

13.1 初认识NodeJS

13-1-1 什么是 Node.js

image-20230801231739381

13-1-2 Node.js 中的 JavaScript 运行环境

image-20230801231817137

13-1-3 Node.js 可以做什么

image-20230801231913311

13.2 fs 文件系统模块

13-2-1 什么是 fs 文件系统模块

fs 模块是 Node.js 官方提供的、用来操作文件的模块。它提供了一系列的方法和属性,用来满足用户对文件的操作需求。

例如:

⚫ fs.readFile() 方法,用来读取指定文件中的内容

⚫ fs.writeFile() 方法,用来向指定的文件中写入内容

如果要在 JavaScript 代码中,使用 fs 模块来操作文件,则需要使用如下的方式先导入它:

image-20230801232138549

13-2-2 读取指定文件中的内容

2-1 fs.readFile() 的语法格式

image-20230801232234806

image-20230801232244875

2-2 fs.readFile() 的示例代码

以 utf8 的编码格式,读取指定文件的内容,并打印 err 和 dataStr 的值:

image-20230801232319738

2-3 判断文件是否读取成功

可以判断 err 对象是否为 null,从而知晓文件读取的结果:

image-20230801232341947

13-2-3 向指定的文件中写入内容

3-1 s.writeFile() 的语法格式

使用 fs.writeFile() 方法,可以向指定的文件中写入内容,语法格式如下:

image-20230801232441570

image-20230801232452395

3-2 fs.writeFile() 的示例代码

image-20230801232509936

3-3 判断文件是否写入成功

image-20230801232527067

13-2-4 fs 模块 - 路径动态拼接的问题

在使用 fs 模块操作文件时,如果提供的操作路径是以 ./ 或 …/ 开头的相对路径时,很容易出现路径动态拼接错误的问题。

原因:代码在运行的时候,会以执行 node 命令时所处的目录,动态拼接出被操作文件的完整路径。

解决方案:在使用 fs 模块操作文件时,直接提供完整的路径,不要提供 ./ 或 …/ 开头的相对路径,从而防止路径动态拼接的问题。

image-20230801232628652

13.3 path 路径模块

13-3-1 什么是 path 路径模块

image-20230801232738559

image-20230801232743724

13-3-2 路径拼接

2-1 path.join()的语法格式

使用 path.join() 方法,可以把多个路径片段拼接为完整的路径字符串,语法格式如下:

image-20230801232832406

参数解读:

⚫ …paths 路径片段的序列

⚫ 返回值:

2-2 path.join() 的代码示例

使用 path.join() 方法,可以把多个路径片段拼接为完整的路径字符串:

image-20230801232905952

注意:今后凡是涉及到路径拼接的操作,都要使用 path.join() 方法进行处理。不要直接使用 + 进行字符串的拼接

13-3-3 获取路径中的文件名

3-1 path.basename() 的语法格式

使用 path.basename() 方法,可以获取路径中的最后一部分,经常通过这个方法获取路径中的文件名,语法格式如下:

image-20230801233008666

image-20230801233020445

3-2 path.basename() 的代码示例

image-20230801233102022

3-3 path.extname() 的语法格式

使用 path.extname() 方法,可以获取路径中的扩展名部分,语法格式如下:

image-20230801233207702

image-20230801233215516

3-4 path.extname() 的代码示例

image-20230801233237160

13.4 http 模块

13-4-1 什么是 http 模块

image-20230801233342751

如果要希望使用 http 模块创建 Web 服务器,则需要先导入它:

image-20230801233351535

13-4-2 进一步理解 http 模块的作用

服务器和普通电脑的区别在于,服务器上安装了 web 服务器软件,例如:IIS、Apache 等。通过安装这些服务器软件,就能把一台普通的电脑变成一台 web 服务器。

在 Node.js 中,我们不需要使用 IIS、Apache 等这些第三方 web 服务器软件。因为我们可以基于 Node.js 提供的http 模块,通过几行简单的代码,就能轻松的手写一个服务器软件,从而对外提供 web 服务。

13-4-3 创建最基本的 web 服务器

3-1 创建 web 服务器的基本步骤

image-20230801233541703

3-2 步骤1 - 导入 http 模块

image-20230801233609654

3-3 步骤2 - 创建 web 服务器实例

调用 http.createServer() 方法,即可快速创建一个 web 服务器实例:

image-20230801233634506

3-4 步骤3 - 为服务器实例绑定 request 事件

为服务器实例绑定 request 事件,即可监听客户端发送过来的网络请求:

image-20230801233659273

3-5 步骤4 - 启动服务器

调用服务器实例的 .listen() 方法,即可启动当前的 web 服务器实例:

image-20230801233721985

13-4-4 req 请求对象

只要服务器接收到了客户端的请求,就会调用通过 server.on() 为服务器绑定的 request 事件处理函数。如果想在事件处理函数中,访问与客户端相关的数据属性,可以使用如下的方式:

image-20230801233759487

13-4-5 res 响应对象

在服务器的 request 事件处理函数中,如果想访问与服务器相关的数据属性,可以使用如下的方式:

image-20230801233851161

13-4-6 解决中文乱码问题

当调用 res.end() 方法,向客户端发送中文内容的时候,会出现乱码问题,此时,需要手动设置内容的编码格式:

image-20230801233940088

13-4-7 根据不同的 url 响应不同的 html 内容

7-1 核心实现步骤

image-20230801234029002

7-2 动态响应内容

image-20230801234049409

13.5 Node.js 中模块的

13-5-1 Node.js 中模块的分类

image-20230801234408879

13-5-2 加载模块

使用强大的 require() 方法,可以加载需要的内置模块、用户自定义模块、第三方模块进行使用。例如:

image-20230801234442591

13-5-3 Node.js 中的模块作用域

3-1 什么是模块作用域

和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域

image-20230801234601762

3-2 模块作用域的好处

防止了全局变量污染的问题

image-20230801234637081

13-5-4 向外共享模块作用域中的成员

4-1 module对象

在每个 .js 自定义模块中都有一个 module 对象,它里面存储了和当前模块有关的信息,打印如下:

image-20230801234735499

4-2 module.exports 对象

在自定义模块中,可以使用 module.exports 对象,将模块内的成员共享出去,供外界使用。外界用 require() 方法导入自定义模块时,得到的就是 module.exports 所指向的对象。

4-3 共享成员时的注意点

使用 require() 方法导入模块时,导入的结果,永远以 module.exports 指向的对象为准

image-20230801234840058

4-4 exports 对象

由于 module.exports 单词写起来比较复杂,为了简化向外共享成员的代码,Node 提供了 exports 对象。默认情况下,exports 和 module.exports 指向同一个对象。最终共享的结果,还是以 module.exports 指向的对象为准。

image-20230801234906944

4-5 exports 和 module.exports 的使用误区

时刻谨记,require() 模块时,得到的永远是 module.exports 指向的对象:

image-20230801235005737

13-5-5 Node.js 中的模块化规范

image-20230801235037363

13.6 模块的加载机制

13-6-1 优先从缓存中加载

模块在第一次加载后会被缓存。 这也意味着多次调用 require() 不会导致模块的代码被执行多次。

注意:不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。

13-6-2 内置模块的加载机制

内置模块是由 Node.js 官方提供的模块,内置模块的加载优先级最高。

例如,require(‘fs’) 始终返回内置的 fs 模块,即使在 node_modules 目录下有名字相同的包也叫做 fs。

13-6-3 自定义模块的加载机制

image-20230801235304847

13-6-4 第三方模块的加载机制

image-20230801235335400

13-6-5 目录作为模块

image-20230801235401194

13.7 Express

13-7-1 初识 Express

1-1 什么是 Express

image-20230801235659438

1-2 Express 能做什么

image-20230801235753624

1-3 Express 的基本使用
3-1 安装

image-20230801235829623

3-2 创建基本的 Web 服务器

image-20230801235848695

3-3 监听 GET 请求

通过 app.get() 方法,可以监听客户端的 GET 请求,具体的语法格式如下:

image-20230801235915126

3-4 监听 POST 请求

通过 app.post() 方法,可以监听客户端的 POST 请求,具体的语法格式如下:

image-20230801235944273

3-5 把内容响应给客户端

通过 res.send() 方法,可以把处理好的内容,发送给客户端

image-20230802000011128

3-6 获取 URL 中携带的查询参数

通过 req.query 对象,可以访问到客户端通过查询字符串的形式,发送到服务器的参数

image-20230802000044366

3-7 获取 URL 中的动态参数

通过 req.params 对象,可以访问到 URL 中,通过 : 匹配到的动态参数:

image-20230802000139100

1-4 托管静态资源
4-1 express.static()

express 提供了一个非常好用的函数,叫做 express.static(),通过它,我们可以非常方便地创建一个静态资源服务器,

例如,通过如下代码就可以将 public 目录下的图片、CSS 文件、JavaScript 文件对外开放访问了:

image-20230802000239339

image-20230802000251774

4-2 托管多个静态资源目录

如果要托管多个静态资源目录,请多次调用 express.static() 函数

image-20230802000316663

访问静态资源文件时,express.static() 函数会根据目录的添加顺序查找所需的文件。

4-3 挂载路径前缀

如果希望在托管的静态资源访问路径之前,挂载路径前缀,则可以使用如下的方式:

image-20230802000401650

image-20230802000422774

1-5 nodemon
5-1 为什么要使用 nodemon

image-20230802000506919

5-2 安装 nodemon

image-20230802000525524

5-3 使用 nodemon

当基于 Node.js 编写了一个网站应用的时候,传统的方式,是运行 node app.js 命令,来启动项目。这样做的坏处是:代码被修改之后,需要手动重启项目。

现在,我们可以将 node 命令替换为 nodemon 命令,使用 nodemon app.js 来启动项目。这样做的好处是:代码被修改之后,会被 nodemon 监听到,从而实现自动重启项目的效果。

image-20230802000558461

13-7-2 Express 路由

2-1 路由的概念
1-1 Express 中的路由

在 Express 中,路由指的是客户端的请求与服务器处理函数之间的映射关系。

Express 中的路由分 3 部分组成,分别是请求的类型、请求的 URL 地址、处理函数,格式如下:

image-20230802000729369

1-2 Express 中的路由的例子

image-20230802000804602

1-3 路由的匹配过程

image-20230802000843945

2-2 路由的使用
2-1 最简单的用法

在 Express 中使用路由最简单的方式,就是把路由挂载到 app 上,示例代码如下:

image-20230802000951658

2-2 模块化路由

image-20230802001025496

2-3 创建路由模块

image-20230802001042804

2-4 注册路由模块

image-20230802001115019

2-5 为路由模块添加前缀

类似于托管静态资源时,为静态资源统一挂载访问前缀一样,路由模块添加前缀的方式也非常简单:

image-20230802001145894

13-7-3 Express 中间件

3-1 中间件的概念
1-1 什么是中间件

中间件(Middleware ),特指业务流程的中间处理环节

1-2 现实生活中的例子

image-20230802001255141

1-3 Express 中间件的调用流程

当一个请求到达 Express 的服务器之后,可以连续调用多个中间件,从而对这次请求进行预处理。

image-20230802001321866

1-4 Express 中间件的格式

Express 的中间件,本质上就是一个 function 处理函数,Express 中间件的格式如下:

image-20230802001348545

注意:中间件函数的形参列表中,必须包含 next 参数。而路由处理函数中只包含 req 和 res。

1-5 next 函数的作用

next 函数是实现多个中间件连续调用的关键,它表示把流转关系转交给下一个中间件或路由。

image-20230802001428523

3-2 Express 中间件的初体验
2-1 定义中间件函数

可以通过如下的方式,定义一个最简单的中间件函数

image-20230802001526514

2-2 全局生效的中间件

客户端发起的任何请求,到达服务器之后,都会触发的中间件,叫做全局生效的中间件。

通过调用 app.use(中间件函数),即可定义一个全局生效的中间件,示例代码如下:

image-20230802001608118

2-3 定义全局中间件的简化形式

image-20230802001642084

2-4 中间件的作用

多个中间件之间,共享同一份 req res。基于这样的特性,我们可以在上游的中间件中,统一为 req 或 res 对象添

加自定义的属性或方法,供下游的中间件或路由进行使用。

image-20230802001726052

2-5 定义多个全局中间件

可以使用 app.use() 连续定义多个全局中间件。客户端请求到达服务器之后,会按照中间件定义的先后顺序依次进行调用,示例代码如下:

image-20230802001755686

2-6 局部生效的中间件

不使用 app.use() 定义的中间件,叫做局部生效的中间件,示例代码如下:

image-20230802001833230

2-7 定义多个局部中间件

可以在路由中,通过如下两种等价的方式,使用多个局部中间件:

image-20230802001859425

2-8 了解中间件的5个使用注意事项

image-20230802001932735

3-3 中间件的分类

image-20230802002013944

3-1 应用级别的中间件

通过 app.use() 或 app.get() 或 app.post() ,绑定到 app 实例上的中间件,叫做应用级别的中间件,代码示例如下:

image-20230802002048054

3-2 路由级别的中间件

绑定到 express.Router() 实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不\过,应用级别中间件是绑定到 app 实例上,路由级别中间件绑定到 router 实例上,代码示例如下:

image-20230802002131376

3-3 错误级别的中间件

错误级别中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。

格式:错误级别中间件的 function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是 (err, req, res, next)。

image-20230802002223620

**注意:**错误级别的中间件,必须注册在所有路由之后!

错误级别中间件的 function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是 (err, req, res, next)。

image-20230802002311669

3-4 Express内置的中间件

image-20230802002352984

image-20230802002400375

3-5 第三方的中间件

image-20230802002427284

3-4 自定义中间件
4-1 需求描述与实现步骤

image-20230802002545621

4-2 定义中间件

使用 app.use() 来定义全局生效的中间件,代码如下:

image-20230802002612258

4-3 监听 req 的 data事件

在中间件中,需要监听 req 对象的 data 事件,来获取客户端发送到服务器的数据。

如果数据量比较大,无法一次性发送完毕,则客户端会把数据切割后,分批发送到服务器。所以 data 事件可能会触

发多次,每一次触发 data 事件时,获取到数据只是完整数据的一部分,需要手动对接收到的数据进行拼接。

image-20230802002647754

4-4 监听 req 的end事件

当请求体数据接收完毕之后,会自动触发 req 的 end 事件。

因此,我们可以在 req 的 end 事件中,拿到并处理完整的请求体数据。示例代码如下:

image-20230802002722699

4-5 使用 querystring 模块解析请求体数据

Node.js 内置了一个 querystring 模块,专门用来处理查询字符串。通过这个模块提供的 parse() 函数,可以轻松把查询字符串,解析成对象的格式。示例代码如下

image-20230802002753068

4-6 将解析出来的数据对象挂载为req.body

上游的中间件和下游的中间件及路由之间,共享同一份 req 和 res。因此,我们可以将解析出来的数据,挂载为 req 的自定义属性,命名为 req.body,供下游使用。示例代码如下:

image-20230802002835411

4-7 将自定义中间件封装为模块

为了优化代码的结构,我们可以把自定义的中间件函数,封装为独立的模块,示例代码如下:

image-20230802002905390

13-7-4 使用 Express 写接口

4-1 创建基本的服务器

image-20230802002936346

4-2 创建 API 路由模块

image-20230802003004846

4-3 编写 GET 接口

image-20230802003042086

4-4 编写 POST 接口

image-20230802003056824

4-5 CORS 跨域资源共享
5-1 接口的跨域问题

image-20230802003142948

5-2 使用cors 中间件解决跨域问题

image-20230802003217555

5-3 什么是 CORS

image-20230802003238703

5-4 CORS 的注意事项

image-20230802003308642

5-5 CORS 响应头部 - Access-Control-Allow-Origin

响应头部中可以携带一个 Access-Control-Allow-Origin 字段,其语法如下:

image-20230802003342713

其中,origin 参数的值指定了允许访问该资源的外域 URL。

例如,下面的字段值将只允许来自 http://itcast.cn 的请求:

image-20230802003355277

如果指定了 Access-Control-Allow-Origin 字段的值为通配符 *****,表示允许来自任何域的请求,示例代码如下:

image-20230802003411443

5-6 CORS 响应头部 - Access-Control-Allow-Headers

image-20230802003458220

image-20230802003507275

5-7 CORS 响应头部 - Access-Control-Allow-Methods

在这里插入图片描述

在这里插入图片描述

5-8 CORS请求的分类

在这里插入图片描述

5-9 简单请求

在这里插入图片描述

5-10 预检请求

在这里插入图片描述

5-11 简单请求和预检请求的区别

image-20230802003714213

4-6 JSONP 接口
6-1 回顾 JSONP 的概念与特点

image-20230802003813133

6-2 创建 JSONP 接口的注意事项

如果项目中已经配置了 CORS 跨域资源共享,为了防止冲突,必须在配置 CORS 中间件之前声明 JSONP 的接口。否则JSONP 接口会被处理成开启了 CORS 的接口。示例代码如下:

image-20230802003842912

6-3 实现 JSONP 接口的步骤

image-20230802003905474

6-4 实现 JSONP 接口的具体代码

image-20230802003922857

6-5 在网页中使用 jQuery 发起 JSONP 请求

调用 $.ajax() 函数,提供 JSONP 的配置选项,从而发起 JSONP 请求,示例代码如下:

image-20230802003953525

13.8 数据库与身份认证

13-8-1 在项目中操作mysql

1-1 在项目中操作数据库的步骤

image-20230802223148917

1-2 安装与配置 mysql 模块
2-1 安装 mysql 模块

mysql 模块是托管于 npm 上的第三方模块。它提供了在 Node.js 项目中连接和操作 MySQL 数据库的能力。

想要在项目中使用它,需要先运行如下命令,将 mysql 安装为项目的依赖包

image-20230802223240050

2-2 配置 mysql 模块

在使用 mysql 模块操作 MySQL 数据库之前,必须先对 mysql 模块进行必要的配置,主要的配置步骤如下:

image-20230802223307013

2-3 测试 mysql 模块能否正常工作

调用 db.query() 函数,指定要执行的 SQL 语句,通过回调函数拿到执行的结果:

image-20230802223336218

1-3 使用 mysql 模块操作 MySQL 数据库
3-1 查询数据

查询 users 表中所有的数据:

image-20230802223434431

3-2 插入数据

向 users 表中新增数据, 其中 username 为 Spider-Man,password 为 pcc321。示例代码如下:

image-20230802223457709

3-3 插入数据的便捷方式

向表中新增数据时,如果数据对象的每个属性和数据表的字段一一对应,则可以通过如下方式快速插入数据:

image-20230802223626942

3-4 更新数据

可以通过如下方式,更新表中的数据

image-20230802223701625

3-5 更新数据的便捷方式

更新表数据时,如果数据对象的每个属性和数据表的字段一一对应,则可以通过如下方式快速更新表数据:

image-20230802223728087

3-6 删除数据

在删除数据时,推荐根据 id 这样的唯一标识,来删除对应的数据。示例如下:

image-20230802223812096

3-7 标记删除

使用 DELETE 语句,会把真正的把数据从表中删除掉。为了保险起见,推荐使用标记删除的形式,来模拟删除的动作

所谓的标记删除,就是在表中设置类似于 status 这样的状态字段,来标记当前这条数据是否被删除。

当用户执行了删除的动作时,我们并没有执行 DELETE 语句把数据删除掉,而是执行了 UPDATE 语句,将这条数据对应的 status 字段标记为删除即可。

image-20230802223847684

13-8-2 前后端的身份认证

2-1 Web 开发模式

image-20230802223958385

1-1 服务端渲染的 Web 开发模式

服务端渲染的概念:服务器发送给客户端的 HTML 页面,是在服务器通过字符串的拼接,动态生成的。因此,客户端不需要使用 Ajax 这样的技术额外请求页面的数据。代码示例如下

image-20230802224034643

1-2 服务端渲染的优缺点

image-20230802224102479

1-3 前后端分离的 Web 开发模式

前后端分离的概念:前后端分离的开发模式,依赖于 Ajax 技术的广泛应用。简而言之,前后端分离的 Web 开发模式,就是后端只负责提供 API 接口,前端使用 Ajax 调用接口的开发模式。

1-4 前后端分离的优缺点

image-20230802224206580

1-5 如何选择 Web 开发模式

image-20230802224251719

2-2 身份认证
2-1 什么是身份认证

image-20230802224337299

2-2 为什么需要身份认证

image-20230802224357149

2-3 不同开发模式下的身份认证

image-20230802224418751

2-3 Session 认证机制
3-1 HTTP 协议的无状态性

image-20230802224457523

3-2 如何突破HTTP 无状态的限制

image-20230802224534090

3-3 什么是Cookie

image-20230802224601071

3-4 Cookie 在身份认证中的作用

image-20230802224630482

3-5 Cookie 不具有安全性

image-20230802224659556

3-6 提高身份认证的安全性

image-20230802224728165

3-7 Session*的工作原理

在这里插入图片描述

2-4 在 Express 中使用 Session 认证
4-1 安装express-session 中间件

在 Express 项目中,只需要安装 express-session 中间件,即可在项目中使用 Session 认证:

image-20230802224949464

4-2 配置 express-session 中间件

express-session 中间件安装成功后,需要通过 app.use() 来注册 session 中间件,示例代码如下:

image-20230802225021013

4-3 向 session 中存数据

当 express-session 中间件配置成功后,即可通过 req.session 来访问和使用 session 对象,从而存储用户的关键信息:

image-20230802225056932

4-4 从 session 中*取数据

可以直接从 req.session 对象上获取之前存储的数据,示例代码如下:

image-20230802225153614

4-5 清空 session

调用 req.session.destroy() 函数,即可清空服务器保存的 session 信息。

image-20230802225226133

2-5 JWT 认证机制
5-1 了解 Session 认证的局限性

image-20230802225329488

5-2 什么是 JWT

JWT(英文全称:JSON Web Token)是目前最流行跨域认证解决方案

5-3 JWT 的工作原理

image-20230802225406615

总结:用户的信息通过 Token 字符串的形式,保存在客户端浏览器中。服务器通过还原 Token 字符串的形式来认证用户的身份。

5-4 JWT 的组成部分

JWT 通常由三部分组成,分别是 Header(头部)、Payload(有效荷载)、Signature(签名)。

三者之间使用英文的“.”分隔,格式如下:

image-20230802225447448

下面是 JWT 字符串的示例:

image-20230802225457710

5-5 JWT 的三个部分各自代表的含义

image-20230802225549842

image-20230802225555056

5-6 JWT 的使用方式

客户端收到服务器返回的 JWT 之后,通常会将它储存在 localStorage 或 sessionStorage 中。

此后,客户端每次与服务器通信,都要带上这个 JWT 的字符串,从而进行身份认证。推荐的做法是把 JWT 放在 HTTP

请求头的 Authorization 字段中,格式如下:

image-20230802225627921

2-6 在 Express 中使用 JWT
6-1 安装JWT 相关的包

image-20230802225711980

其中:

jsonwebtoken 用于生成 JWT 字符串

express-jwt 用于将 JWT 字符串解析还原成 JSON 对象

6-2 导入JWT 相关的包

image-20230802225745303

6-3 定义 secret 密钥

在这里插入图片描述

image-20230802225817706

6-4 在登录成功后生成 JWT 字符串

调用 jsonwebtoken 包提供的 sign() 方法,将用户的信息加密成 JWT 字符串,响应给客户端:

image-20230802225857015

6-5 将JWT 字符串还原为JSON 对象

在这里插入图片描述

image-20230802230008182

6-6 使用 req.user 获取用户信息

当 express-jwt 这个中间件配置成功之后,即可在那些有权限的接口中,使用 req.user 对象,来访问从 JWT 字符串

中解析出来的用户信息了,示例代码如下:

image-20230802230047862

6-7 捕获解析 JWT 失败后产生的错误

当使用 express-jwt 解析 Token 字符串时,如果客户端发送过来的 Token 字符串过期不合法,会产生一个解析失败

的错误,影响项目的正常运行。我们可以通过 Express 的错误中间件,捕获这个错误并进行相关的处理,示例代码如下:

image-20230802230149693

13-8-3 bcryptjs进行加密

3-1 安装
npm i bcryptjs@2.4.3
3-2 导入 bcryptjs
const bcrypt = require('bcryptjs')
3-3 进行加密
// 对用户的密码,进行 bcrype 加密,返回值是加密之后的密码字符串
userinfo.password = bcrypt.hashSync(userinfo.password, 10)

13-8-4 优化数据验证

4-1 安装 @escook/express-joi 中间件

来实现自动对表单数据进行验证的功能:

npm i @escook/express-joi
4-2 安装 @hapi/joi 包

为表单中携带的每个数据项,定义验证规则:

npm install @hapi/joi@17.1.0
4-3 新建 /schema/user.js

用户信息验证规则模块,并初始化代码如下:

/**
* string() 值必须是字符串
* alphanum() 值只能是包含 a-zA-Z0-9 的字符串
* min(length) 最小长度
* max(length) 最大长度
* required() 值是必填项,不能为 undefined
* pattern(正则表达式) 值必须符合正则表达式的规则
*/

// 用户名的验证规则
const username = joi.string().alphanum().min(1).max(10).required()
// 密码的验证规则
const password = joi.string().pattern(/^[\S]{6,12}$/).required()
// 注册和登录表单的验证规则对象
exports.reg_login_schema = {
// 表示需要对 req.body 中的数据进行验证
body: {
    username,
    password,
    },
}
4-4 修改 /router/user.js 中的代码如下
const express = require('express')
const router = express.Router()
// 导入用户路由处理函数模块
const userHandler = require('../router_handler/user')
// 1. 导入验证表单数据的中间件
const expressJoi = require('@escook/express-joi')
// 2. 导入需要的验证规则对象
const { reg_login_schema } = require('../schema/user')
// 注册新用户
// 3. 在注册新用户的路由中,声明局部中间件,对当前请求中携带的数据进行验证
// 3.1 数据验证通过后,会把这次请求流转给后面的路由处理函数
// 3.2 数据验证失败后,终止后续代码的执行,并抛出一个全局的 Error 错误,进入全局错误级别中间件中进行处理
router.post('/reguser', expressJoi(reg_login_schema), userHandler.regUser)
// 登录
router.post('/login', userHandler.login)
module.exports = router

4-5 在 app.js 的全局错误级别中间件中

捕获验证失败的错误,并把验证失败的结果响应给客户端:

const joi = require('@hapi/joi')
// 错误中间件
app.use(function (err, req, res, next) {
    // 数据验证失败
    if (err instanceof joi.ValidationError) return res.cc(err)
    // 未知错误
    res.cc(err)
})
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐