前后端交互学习笔记(五):express+mysql+身份认证

express+mysql+身份认证

文章目录

  • express+mysql+身份认证
    • express
      • express基本使用
        • 托管静态资源
        • nodemon工具
      • express路由
      • express中间件
        • 中间件的分类
        • 自定义中间件
        • CORS接口跨域问题
    • Mysql
        • 基本概念
        • SQL的使用
        • mysql模块
    • 前后端身份认证
        • 开发模式
        • 身份认证
        • Session 实现
        • JWT认证机制
        • JWT使用

express

express基本使用

Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架。通俗的理解:Express 的作用和 Node.js 内置的 http 模块类似,是专门用来创建 Web 服务器的。express是基于http内置模块封装得来的。Express 的本质:就是一个 npm 上的第三方包,提供了快速创建 Web 服务器的便捷方法。使用 Express,我们可以方便、快速的创建 Web 网站的服务器或 API 接口的服务器。 http://www.expressjs.com.cn/

  1. 安装 npm i express
  2. 基本创建服务器方法:
// 1. 导入 express
const express = require('express')
// 2. 创建 web 服务器
const app = express()
// 4. 监听客户端的 GET 和 POST 请求,并向客户端响应具体的内容
app.get('/user', (req, res) => {
  // 调用 express 提供的 res.send() 方法,向客户端响应一个 JSON 对象
  res.send({ name: 'zs', age: 20, gender: '男' })
})
app.post('/user', (req, res) => {
  // 调用 express 提供的 res.send() 方法,向客户端响应一个 文本字符串
  res.send('请求成功')
})
// 3. 启动 web 服务器
app.listen(80, () => {
  console.log('express server running at http://127.0.0.1')
})
  1. 获取url后面所带的参数,如http://127.0.0.1/user/?id=1,可以使用req.query写法:
app.post('/', (req, res) => {
  // 通过 req.query 可以获取到客户端发送过来的 查询参数
  // 注意:默认情况下,req.query 是一个空对象
  console.log(req.query)
  res.send(req.query)
})
  1. 获取url后面所带着的动态参数,可以使用req.params,使用如下:
// // 注意:这里的 :id 是一个动态的参数
app.get('/user/:ids', (req, res) => {
  // req.params 是动态匹配到的 URL 参数,默认也是一个空对象
  console.log(req.params)
  res.send(req.params)
})
托管静态资源

express 提供了一个非常好用的函数,叫做 express.static(),通过它,我们可以非常方便地创建一个静态资源服务器,例如,通过如下代码就可以将 public 目录下的图片、CSS 文件、JavaScript 文件对外开放访问了。Express 在指定的静态目录中查找文件,并对外提供资源的访问路径。因此,存放静态文件的目录名不会出现在 URL 中

  1. 使用方式:app.use(express.static('文件路径’))
  2. 如果同时托管了多个资源且有相同的名字,谁在上面也就是谁先托管就以谁为准,要想区分开,则在前面再加一个网址进行区分,如:
app.use('/files', express.static('./files'))

nodemon工具

在编写调试 Node.js 项目的时候,如果修改了项目的代码,则需要频繁的手动 close 掉,然后再重新启动,非常繁琐。现在,我们可以使用 nodemon(https://www.npmjs.com/package/nodemon) 这个工具,它能够监听项目文件的变动,当代码被修改后,nodemon 会自动帮我们重启项目,极大方便了开发和调试。

  1. 安装:npm install -g nodemon
  2. 使用:nodemon 文件名

express路由

广义上来讲,路由就是映射关系。在 Express 中,路由指的是客户端的请求与服务器处理函数之间的映射,Express 中的路由分 3 部分组成,分别是请求的类型、请求的 URL 地址、处理函数,格式射关系。

app.方法(路径,处理函数)

匹配路径的时候:按照定义的先后顺序进行匹配
请求类型和请求的URL同时匹配成功,才会调用对应的处理函数

  1. 类似与之前的写法挂载到app上,但是实际中不会把所有的都挂在一个上面,通常是进行模块化管理,步骤如下:
    • 创建路由模块对应的 .js 文件
    • 调用 express.Router() 函数创建路由对象
    • 向路由对象上挂载具体的路由
    • 使用 module.exports 向外共享路由对象
    • 使用 app.use() 函数注册路由模块
  2. 在对应的路由模块(一个单独的js模块)里书写的内容示例如下:
// 这是路由模块
// 1. 导入 express
const express = require('express')
// 2. 创建路由对象
const router = express.Router()

// 3. 挂载具体的路由
router.get('/user/list', (req, res) => {
  res.send('Get user list.')
})
router.post('/user/add', (req, res) => {
  res.send('Add new user.')
})

// 4. 向外导出路由对象
module.exports = router
  1. 引入该路由模块的方法:
const express = require('express')
const app = express()

// app.use('/files', express.static('./files'))

// 1. 导入路由模块
const router = require('./03.router')
// 2. 注册路由模块(如果前面加了前缀,那么使用路由函数的时候前面都要加上这个前缀)
app.use('/api', router)

// 注意: app.use() 函数的作用,就是来注册全局中间件

app.listen(80, () => {
  console.log('http://127.0.0.1')
})

express中间件

  1. 当一个请求到达 Express 的服务器之后,可以连续调用多个中间件,(理解为先经过中间件处理之后再进行处理)从而对这次请求进行预处理。中间件是一个函数,简单的定义如下:
// 定义一个最简单的中间件函数
const mw = function (req, res, next) {
  console.log('这是最简单的中间件函数')
  // 把流转关系,转交给下一个中间件或路由
  next()
}
// 将 mw 注册为全局生效的中间件
app.use(mw)
//简写
app.use(function(req,res,next){
......
})
  1. 中间件定义了一个属性,下面所有的都可以进行使用,方便,多个中间件,会依次执行
  2. 定义局部的中间件,不适用app.use,那个路由用就在其第二个参数写上改中间件的名字即可,多个的话,逗号分隔即可
// 1. 定义中间件函数
const mw1 = (req, res, next) => {
  console.log('调用了局部生效的中间件')
  next()
}
// 2. 创建路由
app.get('/', mw1, (req, res) => {
  res.send('Home page.')
})
  1. 一定要在路由之前注册中间件,为了防止代码逻辑混乱,调用 next() 函数后不要再写额外的代码。
中间件的分类
  1. 通过 app.use() 或 app.get() 或 app.post() ,绑定到 app 实例上的中间件,叫做应用级别的中间件
  2. 绑定到 express.Router() 实例上的中间件,叫做路由级别的中间件。它的用法和应用级别中间件没有任何区别。只不过,应用级别中间件是绑定到 app 实例上,路由级别中间件绑定到 router 实例上。
  3. 错误级别中间件的作用:专门用来捕获整个项目中发生的异常错误,从而防止项目异常崩溃的问题。格式:错误级别中间件的 function 处理函数中,必须有 4 个形参,形参顺序从前到后,分别是 (err, req, res, next)。注意:错误级别的中间件,必须注册在所有路由之后!
  4. 内置中间件便于对接收到的数据进行解析
    前后端交互学习笔记(五):express+mysql+身份认证_第1张图片
// 注意:除了错误级别的中间件,其他的中间件,必须在路由之前进行配置
// 通过 express.json() 这个中间件,解析表单中的 JSON 格式的数据
app.use(express.json())//在下面服务器
// 通过 express.urlencoded() 这个中间件,来解析 表单中的 url-encoded 格式的数据
app.use(express.urlencoded({ extended: false }))

app.post('/user', (req, res) => {
  // 在服务器,可以使用 req.body 这个属性,来接收客户端发送过来的请求体数据
  // 默认情况下,如果不配置解析表单数据的中间件,则 req.body 默认等于 undefined
  console.log(req.body)
  res.send('ok')
})

app.post('/book', (req, res) => {
  // 在服务器端,可以通过 req,body 来获取 JSON 格式的表单数据和 url-encoded 格式的数据
  console.log(req.body)
  res.send('ok')
})
  1. 第三方 使用步骤即:运行 npm install 名字 安装中间件;使用 require 导入中间件;调用 app.use() 注册并使用中间件。
自定义中间件
// 这是解析表单数据的中间件
app.use((req, res, next) => {
  // 定义中间件具体的业务逻辑
  // 1. 定义一个 str 字符串,专门用来存储客户端发送过来的请求体数据
  let str = ''
  // 2. 监听 req 的 data 事件
  req.on('data', (chunk) => {
    str += chunk
  })
  // 3. 监听 req 的 end 事件
  req.on('end', () => {
    // 在 str 中存放的是完整的请求体数据
    // console.log(str)
    // TODO: 把字符串格式的请求体数据,解析成对象格式
    const body = qs.parse(str)//qs.parse()解析成对象的形式
    req.body = body
    next()
  })
})
CORS接口跨域问题
  1. cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件,可以很方便地解决跨域问题。CORS 主要在服务器端进行配置。客户端浏览器无须做任何额外的配置
  2. CORS响应头部:
  • Access-Control-Allow-Origin 字段的值为通配符 *或者是具体的请求地址。
  • Access-Control-Allow-Headers 对额外的请求头进行声明,默认情况下,CORS 仅支持客户端向服务器发送如下的 9 个请求头
  • Access-Control-Alow-Methods来指明实际请求所允许使用的 HTTP 方法。默认情况下,CORS 仅支持客户端发起 GET、POST、HEAD 请求。
  1. 简单请求,符合上述默认条件的(9请求头中一个、请求方式中一个),客户端与服务器之间只会发生一次请求。
    预检请求,不符合上述简单请求,并且向服务器发送了 application/json 格式的数据。特点:客户端与服务器之间会发生两次请求,OPTION 预检请求成功之后,才会发起真正的请求。
    4.如果项目中已经配置了 CORS 跨域资源共享,为了防止冲突,必须在配置 CORS 中间件之前声明 JSONP 的接口。否则 JSONP 接口会被处理成开启了 CORS 的接口。

Mysql

基本概念
  1. 在传统型数据库中,数据的组织结构分为数据库(database)、数据表(table)、数据行(row)、字段(field)这 4 大部分组成。
  2. 在实际项目开发中,一般情况下,每个项目都对应独立的数据库。不同的数据,要存储到数据库的不同表中。表中的行,代表每一条具体的数据。
  3. 字段的特殊标识(tinyint(1)1暂且理解为长度,只能是一位数):
    前后端交互学习笔记(五):express+mysql+身份认证_第2张图片
SQL的使用
  1. SQL(英文全称:Structured Query Language)是结构化查询语言,专门用来访问和处理数据库的编程语言。能够让我们以编程的形式,操作数据库里面的数据,SQL 语言只能在关系型数据库中使用。
  2. 选择数据:select 多个列用逗号隔开 form 表
  3. 插入数据:
    前后端交互学习笔记(五):express+mysql+身份认证_第3张图片
  4. 更新数据,修改多个的时候也用都好隔开
    前后端交互学习笔记(五):express+mysql+身份认证_第4张图片
  5. 删除数据:
    前后端交互学习笔记(五):express+mysql+身份认证_第5张图片
  6. where常用的符号总结如下:在某些版本的 SQL 中,操作符 <> 可以写为 !=
    前后端交互学习笔记(五):express+mysql+身份认证_第6张图片
    SQL中用到直接是and or
  7. 排序:ORDER BY 语句用于根据指定的列对结果集进行排序。默认按照升序对记录进行排序(ASC可以省略)。如果希望按照降序对记录进行排序,可以使用 DESC 关键字。举例如下:
    在这里插入图片描述
    多重排序,order by后面用逗号隔开
  8. COUNT(*) 函数用于返回查询结果的总数据条数,默认的列也为COUNT,下述也可以用where加上条件
    在这里插入图片描述
  9. 如果希望给查询出来的列名称设置别名,可以使用 AS 关键字
    在这里插入图片描述
mysql模块
  1. 使用npm i mysql 在项目目录下添加mysql模块
  2. 在配置的js文件中进行数据库的配置,常用的配置如下所示:
import mysql from 'mysql'//es6的写法
const mysql=require('mysql')

const pool = mysql.createPool({
  host: '127.0.0.1',
  port: 3306,
  database: 'my_db_01',
  user: 'root',
  password: 'admin123',
})
  1. 进行sql语句书写的举例,如下所示:注意select返回的是一个数组,其它返回的是一个对象,里面的affectedRows属性可以判断是否操作成功
    前后端交互学习笔记(五):express+mysql+身份认证_第7张图片
  2. 插入语句的书写举例:特别要注意的是可以用?进行占位,使用的时候在后面用数组(可以用user变量替换)添加对应的数

前后端交互学习笔记(五):express+mysql+身份认证_第8张图片更新和插入快捷方式,该有的都有的请情况下:前后端交互学习笔记(五):express+mysql+身份认证_第9张图片
5. 如果SQL语句中有多个占位符,则必须使用数组为每个占位符指定具体的值 如果SQL语句中只有一个占位符,则可以省略数组

前后端身份认证

开发模式
  • 服务端渲染的概念:服务器发送给客户端的 HTML 页面,是在服务器通过字符串的拼接,动态生成的。因此,客户端不需要使用 Ajax 这样的技术额外请求页面的数据。耗时少,有利于爬虫,但是占用资源,不利于前后端开发
  • 前后端分离的概念:前后端分离的开发模式,依赖于 Ajax 技术的广泛应用。简而言之,前后端分离的 Web 开发模式,就是后端只负责提供 API 接口,前端使用 Ajax 调用接口的开发模式。用户体验好,减轻服务器的压力,不利于爬虫.
  • 企业级网站,主要功能是展示而没有复杂的交互,并且需要良好的 SEO,则这时我们就需要使用服务器端渲染;而类似后台管理项目,交互性比较强,那么就可以使用前后端分离的开发模式。另外,具体使用何种开发模式并不是绝对的,为了同时兼顾了首页的渲染速度和前后端分离的开发效率,一些网站采用了首屏服务器端渲染 + 其他页面前后端分离的开发模式。
身份认证
  1. 身份认证(Authentication)又称“身份验证”、“鉴权”,是指通过一定的手段,完成对用户身份的确认。服务端渲染推荐使用 Session 认证机制。前后端分离推荐使用 JWT 认证机制
  2. HTTP 协议的无状态性,指的是客户端的每次 HTTP 请求都是独立的,连续多个请求之间没有直接的关系,服务器不会主动保留每次 HTTP 请求的状态。
  3. web开发中用于保留用户身份的叫Cookie。Cookie 是存储在用户浏览器中的一段不超过 4 KB 的字符串。它由一个名称(Name)、一个值(Value)和其它几个用于控制 Cookie 有效期、安全性、使用范围的可选属性组成。不同域名下的 Cookie 各自独立,每当客户端发起请求时,会自动把当前域名下(此时是同一网站,不同网站之间是相互独立的)所有未过期的 Cookie 一同发送到服务器。第一次,服务器通过响应头将Cookie发给服务器,随后的访问都是通过请求头的形式将未过期的所有cookie发送给服务器
  4. cookie不具有安全性,因此可以在服务器上对cooki进行验证
Session 实现
  1. 首先,在项目中,安装中间件:npm install express-session
  2. 然后再js文件中进行配置,secret代表加密的方式:
    前后端交互学习笔记(五):express+mysql+身份认证_第10张图片
  3. 当 express-session 中间件配置成功后,即可通过 req.session 来访问和使用 session 对象,调用 req.session.destroy() 函数,即可清空服务器保存的 session 信息。举例如下:像req.session.user是session中的固定写法
    在这里插入图片描述
JWT认证机制
  1. 当前端请求后端接口不存在跨域问题的时候,推荐使用 Session 身份认证机制。
    当前端需要跨域请求后端接口的时候,不推荐使用 Session 身份认证机制,推荐使用 JWT 认证机制。
  2. JWT中用户的信息通过 Token 字符串的形式,保存在客户端浏览器中。服务器通过还原 Token 字符串的形式来认证用户的身份。而session信息是保存在服务器中的
  3. JWT 通常由三部分组成,分别是 Header(头部)、Payload(有效荷载)、Signature(签名)。Payload 部分才是真正的用户信息,它是用户信息经过加密之后生成的字符串。Header 和 Signature 是安全性相关的部分,只是为了保证 Token 的安全性。
JWT使用
  1. 首先安装包 npm i jsonwebtoken express-jwt 。jsonwebtoken 用于生成 JWT 字符串。express-jwt 用于将 JWT 字符串解析还原成 JSON 对象
  2. 为了保证 JWT 字符串的安全性,防止 JWT 字符串在网络传输过程中被别人破解,我们需要专门定义一个用于加密和解密的 secret 密钥。当生成 JWT 字符串的时候,需要使用 secret 密钥对用户的信息进行加密,最终得到加密好的 JWT 字符串。当把 JWT 字符串解析还原成 JSON 对象的时候,需要使用 secret 密钥进行解密
// 定义 secret 密钥,建议将密钥命名为 secretKey
const secretKey = 'itheima No1 ^_^'
  1. 生成JWT字符串的方法:
app.post('/api/login', function (req, res) {
  const userinfo = req.body
  // 在登录成功之后,调用 jwt.sign() 方法生成 JWT 字符串。并通过 token 属性发送给客户端
  // 参数1:用户的信息对象
  // 参数2:加密的秘钥
  // 参数3:配置对象,可以配置当前 token 的有效期
  // 记住:千万不要把密码加密到 token 字符中
  const tokenStr = jwt.sign({ username: userinfo.username }, secretKey, { expiresIn: '30s' })
  res.send({
    status: 200,
    message: '登录成功!',
    token: tokenStr, // 要发送给客户端的 token 字符串
  })
})
  1. 将token解析为json对象:
// 注册将 JWT 字符串解析还原成 JSON 对象的中间件
// 注意:只要配置成功了 express-jwt 这个中间件,就可以把解析出来的用户信息,挂载到 req.user 属性上
app.use(expressJWT({ secret: secretKey }).unless({ path: [/^\/api\//] }))
  1. 当 express-jwt 这个中间件配置成功之后,即可在那些有权限的接口中,使用 req.user 对象,来访问从 JWT 字符串
    前后端交互学习笔记(五):express+mysql+身份认证_第11张图片
  2. 当使用 express-jwt 解析 Token 字符串时,如果客户端发送过来的 Token 字符串过期或不合法,会产生一个解析失败的错误,影响项目的正常运行。我们可以通过 Express 的错误中间件,捕获这个错误并进行相关的处理,示例代码如下:

前后端交互学习笔记(五):express+mysql+身份认证_第12张图片

你可能感兴趣的:(express,mysql,javascript)