node.js

目录

  • node.js学习(黑马)
    • FS系统
    • PATH路径
    • http模块
    • 模块化
    • nmp与包
    • EXPRESS
      • EXPRESS路由
      • EXPRESS中间件
      • EXPRESS写接口
      • EXPRESS接口编写--接口跨域问题
    • 数据库
    • Web开发模式
      • 服务器端渲染的Web开发模式
      • 前后端分离的Web开发模式
      • 前后端的身份认证

node.js学习(黑马)

FS系统

  1. 使用完整的文件存放路径,绝对路径
  2. 使用__dirname + (__dirname表示当前文件所处目录)
    node.js 路径拼接问题
    解决方法:

PATH路径

首先导入
1.path.join()路径拼接

// 注意:  ../ 
const pathStr = path.join('/a', '/b/c', '../../', './d', 'e')
console.log(pathStr)  // \a\b\d\e
fs.readFile(__dirname + '/files/1.txt')
fs.readFile(path.join(__dirname, './files/1.txt'), 'utf8', function(err, dataStr) {
  if (err) {
    return console.log(err.message)
  }
  console.log(dataStr)
})

2.path.basename()查询文件名称

// 定义文件的存放路径
const fpath = '/a/b/c/index.html'

// const fullName = path.basename(fpath)
// console.log(fullName)

const nameWithoutExt = path.basename(fpath, '.html')
console.log(nameWithoutExt)

3.path.extname()查询文件扩展名

// 这是文件的存放路径
const fpath = '/a/b/c/index.html'

const fext = path.extname(fpath)
console.log(fext)

4.综合案例——对html文件进行拆解html/js/css结构
思想:1.读取html文件
2.正则表达式匹配对应内容(read)
3.根据正则表达式提取内容
3.将拆解出的写入新文件(write)

http模块

node.js提供的用来创建web服务器的模块
1.服务器相关概念
IP地址:互联网上每台计算机的唯一地址
使用ping 来获取其他网站服务器的IP地址
2.域名与域名服务器
域名:字符型的地址方案,与IP地址一一对应,
域名服务器:存放IP地址与域名对应的关系,提供两者之间转换的服务器
3.端口号:门牌号,每个web服务对应一个端口号,每个端口号只对应一个web服务,80端口号可以被省略

4.创建web服务器
首先调用该模块

// 1. 导入 http 模块
const http = require('http')
// 2. 创建 web 服务器实例
const server = http.createServer()
// 3. 为服务器实例绑定 request 事件,监听客户端的请求
server.on('request', function (req, res) {
  console.log('Someone visit our web server.')
})
// 4. 启动服务器
server.listen(8080, function () {  
  console.log('server running at http://127.0.0.1:8080')
})

4.request response 请求 响应对象

const http = require('http')
const server = http.createServer()
// req 是请求对象,包含了与客户端相关的数据和属性
server.on('request', (req, res) => {
  // req.url 是客户端请求的 URL 地址
  const url = req.url
  // req.method 是客户端请求的 method 类型
  const method = req.method
  const str = `Your request url is ${url}, and request method is ${method}`
  console.log(str)
  // 调用 res.end() 方法,向客户端响应一些内容
  res.end(str)
})
server.listen(80, () => {
  console.log('your server running at http://127.0.0.1')
})

5.解决中文乱码——设置响应头
6.时钟clock案例

模块化

1.模块分类:内置模块、自定义模块、第三方模块
加载内置模块与第三方模块相同
自定义模块加载,需要路径

const m1 = require('./06.m1.js')
console.log(m1)

2.模块作用域(与函数作用域一致)
3.module对象:每个自定义模块都有一个module对象,存储了和当前模块的相关信息。
4.module.exports():当外界用require()方法导入对象时,暴露给外界是module.exports指向的对象,exports对象具有覆盖性,最终指向最后挂载的对象。
5.exports对象,其作用与module.exports()相同,但最后暴露给外界的以module.exports指向的对象为准

const age = 20

// 向 module.exports 对象上挂载 username 属性
module.exports.username = 'zs'
// 向 module.exports 对象上挂载 sayHello 方法
module.exports.sayHello = function() {
  console.log('Hello!')
}
module.exports.age = age

// 让 module.exports 指向一个全新的对象
module.exports = {
  nickname: '小黑',
  sayHi() {
    console.log('Hi!')
  }
}

nmp与包

node.js中第三方模块称为包,基于内置模块封装出来的
https://www.npmjs…com
1.包的安装:终端运行 npm install 包名称@包的版本号
2.package.json,置于项目根目录中,记录项目中安装的包
项目开始前,自动创建 npm init -y
3.npm install 根据package.jason一次性安装所有的包
npm uninstall 包名 卸载指定的包
4.package.json dependencies 包含项目所需包
devDependencies 包含项目开发过程中所需要的包,但是 项目上线后不需要的包 使用如下命令安装指定的包并将其放置在devDependecies下 npm i 包名 -D 或者 npm install 包名 --save-dev 包名
5.下载包的镜像源
查看当前的镜像源:npm config get registry
设置其他的镜像源
6.nrm
首先下载nrm
nrm ls 查看所有可用的镜像源
nrm use 源(更换下载源)
7.包的分类:项目包
项目包:放置在node-modules内,分为开发依赖包与核心依赖包
全局包:npm install 命令时,使用了 -g的包,包的位置位于C:\Users\Amanda\AppData\Roaming\npm\node_modules\nrm
8.包的内部结构
包必须以单独的目录而存在、包的顶级目录下必须包含package.json这个包配置管理文件、package.json必须包含name/version/main这三个属性 main指包的入口
9.开发属于自己的包
包的结构:包的根目录:itheima-tools 文件夹
包含如下 三个文件:package.json
index.js(包的入口文件)
readme.md(包的说明文档)包的发布
注册——登陆(npm login)——发布(npm publish)
9.模块的加载机制:模块加载后都会缓存,优先从缓存中加载信息
内置模块:该模块优先级最高
自定义模块:需以.指定以/或者…/路径标识符为开头,否则会加载成内置模块或者第三方模块,注:在require()导入自定义模块时,若忽略了文件的扩展名,则分别按如下顺序加载文件:确切的文件名——.js——.json——.node
第三方模块:
目录作为模块加载:优先从被加载目录中查询package.json文件,并寻找main属性作为require加载入口——否则,则加载目录下的index.js文件——否则,报错

EXPRESS

express服务器基本使用:导入——创建对象实例——启动

//引入express并创建应用对象
const express = require('express')
const app = express()
//监听端口启动服务
app.listen(8000, ()=>{
    console.log('服务已经启动,端口8000监听中')
})

获取GET/POST请求

// 1. 导入 express
const express = require('express')
// 2. 创建 web 服务器
const app = express()

// 3. 监听客户端的 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('请求成功')
})
//监听端口启动服务
app.listen(8000, ()=>{
    console.log('服务已经启动,端口8000监听中')
})

req.query :获取客户端查询过来的参数
req.params:访问url中,通过: 匹配的参数
express.static():静态资源托管,被托管的文件夹名不会出现在路径URL中,先托管的文件先起作用

const express = require('express')
const app = express()

// 在这里,调用 express.static() 方法,快速的对外提供静态资源

// 在托管的静态资源访问路径之前,挂载路径前缀,则必须通过该前缀所在路径访问文件
app.use('/files', express.static('./files'))
// 普通的静态资源托管
app.use(express.static('./clock'))

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

nodemon 服务器的自动重启,一旦服务器内容发生改变,则自动重启服务器

EXPRESS路由

路由:指客户端的请求与服务器处理函数之间的映射关系
express路由三部分组成:请求的类型、请求的url地址、处理函数
模块化的路由:

// 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

导入模块化的路由:

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.其本质为function,与路由处理函数的不同之处在于有next形参
2.next函数就是next方法 next(),只有使用了next(),才可以使请求到达下一个路由或中间件
3.将函数注册为全局中间件:app.use()

const express = require('express')
const app = express()

// // 定义一个最简单的中间件函数
// const mw = function (req, res, next) {
//   console.log('这是最简单的中间件函数')
//   // 把流转关系,转交给下一个中间件或路由
//   next()
// }

// // 将 mw 注册为全局生效的中间件
// app.use(mw)

// 这是定义全局中间件的简化形式
app.use((req, res, next) => {
  console.log('这是最简单的中间件函数')
  next()
})

app.get('/', (req, res) => {
  console.log('调用了 / 这个路由')
  res.send('Home page.')
})
app.get('/user', (req, res) => {
  console.log('调用了 /user 这个路由')
  res.send('User page.')
})

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

4.中间件的作用
多个中间件之间,共享同一份req与res,可基于此特性,在上游中间件中,为req或者res添加自定义的属性或方法,供下游的中间件或者路由使用

const express = require('express')
const app = express()

// 这是定义全局中间件的简化形式
app.use((req, res, next) => {
// 获取到请求到达服务器的时间
const time = Date.now()
// 为 req 对象,挂载自定义属性,从而把时间共享给后面的所有路由

req.startTime = time
next()
})

app.get('/', (req, res) => {
res.send('Home page.' + req.startTime)
})
app.get('/user', (req, res) => {
res.send('User page.' + req.startTime)
})

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

5.定义多个全局中间件
利用app.use()定义多个全局中间件,客户端请求到达服务器后,调用顺序根据中间件定义的先后顺序
6.局部中间件,不使用app.use()
7.定义并使用简单的局部中间件

 // 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()

// 1. 定义中间件函数
const mw1 = (req, res, next) => {
console.log('调用了局部生效的中间件')
next()
}

// 2. 创建路由
app.get('/', mw1, (req, res) => {
res.send('Home page.')
})
app.get('/user', (req, res) => {
res.send('User page.')
})

// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
console.log('Express server running at http://127.0.0.1')
})

8.同时使用多个局部中间件

// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()

// 1. 定义中间件函数
const mw1 = (req, res, next) => {
  console.log('调用了第一个局部生效的中间件')
  next()
}

const mw2 = (req, res, next) => {
  console.log('调用了第二个局部生效的中间件')
  next()
}

// 2. 创建路由
app.get('/', [mw1, mw2], (req, res) => {
  res.send('Home page.')
})
app.get('/user', (req, res) => {
  res.send('User page.')
})

// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
  console.log('Express server running at http://127.0.0.1')
})

9.中间件的分类
9.1应用级别的中间件:app.use() app.get() app.post(),绑定到app实例上的中间件

app.use((req, res, next) => {
  console.log('这是最简单的中间件函数')
  next()
})

9.2 路由级别的中间件: express.Router() 绑定到express.Router()实例上的中间件

router.get( (req, res, next) => {
  res.send('Get user list.')
  next()
})

9.3 错误级别的中间件:捕获项目中发生的错误,其function函数中,参数必须有(err,req,res,next),
错误级别中间件必须设置在所有路由后面,以便捕捉错误

/ 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()

// 1. 定义路由
app.get('/', (req, res) => {
  // 1.1 人为的制造错误
  throw new Error('服务器内部发生了错误!')
  res.send('Home page.')
})

// 2. 定义错误级别的中间件,捕获整个项目的异常错误,从而防止程序的崩溃
app.use((err, req, res, next) => {
  console.log('发生了错误!' + err.message) b
  res.send('Error:' + err.message)
})

// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
  console.log('Express server running at http://127.0.0.1')
})

9.4内置中间件
expres.static 快速托管静态资源中间件,例如:HTML文件、图片、css样式等,无兼容性
expres.json 解析json格式的请求体数据,有兼容性
expres.json 解析url-encoded 格式的请求体数据,有兼容性

// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()

// 通过 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')
})

// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
  console.log('Express server running at http://127.0.0.1')
})

9.5第三方的中间件
目前常用body-parser,用来解析请求体数据

// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()

// 1. 导入解析表单数据的中间件 body-parser
const parser = require('body-parser')
// 2. 使用 app.use() 注册中间件
app.use(parser.urlencoded({ extended: false }))
// app.use(express.urlencoded({ extended: false }))

app.post('/user', (req, res) => {
  // 如果没有配置任何解析表单数据的中间件,则 req.body 默认等于 undefined
  console.log(req.body)
  res.send('ok')
})

// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(80, function () {
  console.log('Express server running at http://127.0.0.1')
})

9.6中自定义的中间件
自定义中间件
自定义中间件的模块化以及导入

EXPRESS写接口

基本步骤
1.创建基本服务器
2.创建路由模块

const express = require('express')
const router = express.Router()

// 在这里挂载对应的路由
router.get('/get', (req, res) => {
  // 通过 req.query 获取客户端通过查询字符串,发送到服务器的数据
  const query = req.query
  // 调用 res.send() 方法,向客户端响应处理的结果
  res.send({
    status: 0, // 0 表示处理成功,1 表示处理失败
    msg: 'GET 请求成功!', // 状态的描述
    data: query, // 需要响应给客户端的数据
  })
})

// 定义 POST 接口
router.post('/post', (req, res) => {
  // 通过 req.body 获取请求体中包含的 url-encoded 格式的数据
  const body = req.body
  // 调用 res.send() 方法,向客户端响应结果
  res.send({
    status: 0,
    msg: 'POST 请求成功!',
    data: body,
  })
})

// 定义 DELETE 接口
router.delete('/delete', (req, res) => {
  res.send({
    status: 0,
    msg: 'DELETE请求成功',
  })
})

module.exports = router

3.在1的基础上导入创建的2路由 模块

// 导入 express
const express = require('express')
// 创建服务器实例
const app = express()

// 配置解析表单数据的中间件
app.use(express.urlencoded({ extended: false }))

// 必须在配置 cors 中间件之前,配置 JSONP 的接口
app.get('/api/jsonp', (req, res) => {
  // TODO: 定义 JSONP 接口具体的实现过程
  // 1. 得到函数的名称
  const funcName = req.query.callback
  // 2. 定义要发送到客户端的数据对象
  const data = { name: 'zs', age: 22 }
  // 3. 拼接出一个函数的调用
  const scriptStr = `${funcName}(${JSON.stringify(data)})`
  // 4. 把拼接的字符串,响应给客户端
  res.send(scriptStr)
})

// 一定要在路由之前,配置 cors 这个中间件,从而解决接口跨域的问题
const cors = require('cors')
app.use(cors())

// 导入路由模块
const router = require('./16.apiRouter')
// 把路由模块,注册到 app 上
app.use('/api', router)

// 启动服务器
app.listen(80, () => {
  console.log('express server running at http://127.0.0.1')
})

EXPRESS接口编写–接口跨域问题

接口跨域问题常见的解决方案:
1.jsonp中间件
2.cors中间件:安装此中间件–在编写接口中导入中间件–app.use(cors())配置中间件
附:cors跨域资源共享
一般的请求头: Access-Control-Allow-Origin可携带字段,当字段值为用通配符*,表示允许来自任何域的请求。
设置方式如下:

//设置响应头 设置允许跨域
    response.setHeader('Access-Control-Allow-Origin', '*')

cors响应头部 Access-Control-Allow-Headers,一般仅支持九个请求头,若需要额外的请求头,则在服务器端通过Access-Control-Allow-Headers对额外的请求头进行声明
例:

//设置响应头 设置允许跨域
    response.setHeader('Access-Control-Allow-Headers', 'Content-Type')

cors响应头部 Access-Control-Allow-Methods, 默认情况一般仅支持客户端发起的GET/POST/HEAD请求,若客户端想通过PUT/DELETE等额外的方式请求服务器资源,则在服务器端通过Access-Control-Allow-Methods来指明方法

//设置响应头 设置客户端请求的方法
response.setHeader('Access-Control-Allow-Methods', 'POST, GET, DELETE,HEAD')
//允许所有的请求方法
response.setHeader('Access-Control-Allow-Methods', '*')

3.cors请求分类
3.1简单请求:客户端与服务器之间只发起一次请求。
3.2预检请求:客户端与服务器发起两次请求。
请求方式为GET/POST/HEAD之外的请求;请求头中包含自定义头部字段;向服务器发送了json/application格式的数据(满足以上条件之一的都算)

4.JSONP
概念:浏览器端通过

// 必须在配置 cors 中间件之前,配置 JSONP 的接口
app.get('/api/jsonp', (req, res) => {
  // TODO: 定义 JSONP 接口具体的实现过程
  // 1. 得到函数的名称
  const funcName = req.query.callback
  // 2. 定义要发送到客户端的数据对象
  const data = { name: 'zs', age: 22 }
  // 3. 拼接出一个函数的调用
  const scriptStr = `${funcName}(${JSON.stringify(data)})`
  // 4. 把拼接的字符串,响应给客户端
  res.send(scriptStr)
})

客户端的请求发起(或参照ajax学习):

  $('#btnJSONP').on('click', function () {
          $.ajax({
            type: 'GET',
            url: 'http://127.0.0.1/api/jsonp',
            dataType: 'jsonp',
            success: function (res) {
              console.log(res)
            },
          })
        })

数据库

mysql/oracle/SQL sever属于传统数据库(关系型数据库)
Mongodb新型数据库(非关系型数据库,NoSQL)

Web开发模式

服务器端渲染的Web开发模式

服务器发送给客户端的 HTML 页面,是在服务器通过字符串的拼接,动态生成的。因此,客户端不需要使用 Ajax 这样的技术额外请求页面的数据。
优点:前端耗时少;有利于SEO
缺点:占用服务器端资源;不利于前后端分离

前后端分离的Web开发模式

前后端分离的开发模式,依赖于 Ajax 技术的广泛应用。简而言之,前后端分离的 Web 开发模式,就是后端只负责提供 API 接口,前端使用 Ajax 调用接口的开发模式。
优点:开发体验好;用户体验好;减轻服务器端的渲染压力
缺点:不利于SEO,所以需借助Vue、React等前端框架的ssr技术

前后端的身份认证

① 服务端渲染: Session 认证机制
② 前后端分离: JWT 认证机制
1.Cookie 认证机制
1.1 HTTP 协议的无状态性:客户端的每次 HTTP 请求都是独立的,连续多个请求之间没有直接的关系,服务器不会主动保留每次 HTTP 请求的状态。
解决无状态性:使用Cookie
1.2 Cookie:Cookie 是存储在用户浏览器中的一段不超过 4 KB 的字符串。它由一个名称(Name)、一个值(Value)和其它几个用
于控制 Cookie 有效期、安全性、使用范围的可选属性组成。
不同域名下的 Cookie 各自独立,每当客户端发起请求时,会自动把当前域名下所有未过期的 Cookie 一同发送到服务器。
特点:
① 自动发送
② 域名独立
③ 过期时限
④ 4KB 限制
1.3 Cookie 在身份认证中的作用
在这里插入图片描述
node.js_第1张图片缺点:不具有安全性,Cookie 是存储在浏览器中的,而且浏览器也提供了读写 Cookie
的 API,Cookie 很容易被伪造。不使用Cookie保存隐私数据。
2.Sesion 认证机制
2.1 原理:
node.js_第2张图片
2.2 Express中使用Session机制
步骤:导入Session模块——配置Session中间件

const session = require('express-session')
app.use(
  session({
    secret: 'itheima',
    resave: false,
    saveUninitialized: true,
  })
)

2.3 Session中存储数据:通过req.session来访问与使用session对象,从而存储用户关键信息
2.4 从Session中取数据
2.5清空Session信息:req.session.destroy()
3.JWT(JSON Web Token) 认证机制
3.1工作原理:
node.js_第3张图片
3.2 JWT三个组成成分:Header、Payload、Signature
node.js_第4张图片
3.3 JWT使用方式
客户端收到服务器返回的 JWT 之后,通常会将它以localStorage 或 sessionStorage存储,此后,客户端每次与服务器通信,都要带上这个 JWT 的字符串,从而进行身份认证。推荐的做法是把 JWT 放在 HTTP 请求头的 Authorization 字段中。
3.3 EXPRESS中使用JWT方式:
a. 安装JWT相关包( jsonwebtoken 用于生成 JWT 字符串/express-jwt 用于将 JWT 字符串解析还原成 JSON 对象)
b.导入相关包
c.定义secret密钥(用于JWT字符串生成时加密与JWT字符串转成JSON对象时解密)
d.调用jsonwebtoken提供jwt.sign()方法,生成JWT字符串
e.使用express.jwt中间件:在客户访问有权限的接口时,通过请求头中的Authorization字段,将Token字符串发送到服务器进行身份验证,使用express.jwt中间件将用户发送过来的Token解析还原成JSON对象。
f.req.user对象从JWTz字符串中解析获取用户信息(express新版本中有效负载为req.auth)
代码如下:
g.捕获解析JWT失败后产生的错误:使用EXPRESS错误捕捉中间件

// 导入 express 模块
const express = require('express')
// 创建 express 的服务器实例
const app = express()

// TODO_01:安装并导入 JWT 相关的两个包,分别是 jsonwebtoken 和 express-jwt
const jwt = require('jsonwebtoken')
const expressJWT = require('express-jwt')

// 允许跨域资源共享
const cors = require('cors')
app.use(cors())

// 解析 post 表单数据的中间件
const bodyParser = require('body-parser')
app.use(bodyParser.urlencoded({ extended: false }))

// TODO_02:定义 secret 密钥,建议将密钥命名为 secretKey
const secretKey = 'itheima No1 ^_^'

// TODO_04:注册将 JWT 字符串解析还原成 JSON 对象的中间件
// 注意:只要配置成功了 express-jwt 这个中间件,就可以把解析出来的用户信息,挂载到 req.user 属性上;unless可以配置不需要权限的用户
app.use(expressJWT({ secret: secretKey }).unless({ path: [/^\/api\//] }))

// 登录接口
app.post('/api/login', function (req, res) {
  // 将 req.body 请求体中的数据,转存为 userinfo 常量
  const userinfo = req.body
  // 登录失败
  if (userinfo.username !== 'admin' || userinfo.password !== '000000') {
    return res.send({
      status: 400,
      message: '登录失败!',
    })
  }
  // 登录成功
  // TODO_03:在登录成功之后,调用 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 字符串
  })
})

// 这是一个有权限的 API 接口
app.get('/admin/getinfo', function (req, res) {
  // TODO_05:使用 req.user 获取用户信息,并使用 data 属性将用户信息发送给客户端
  console.log(req.user)
  res.send({
    status: 200,
    message: '获取用户信息成功!',
    data: req.user, // 要发送给客户端的用户信息
  })
})

// TODO_06:使用全局错误处理中间件,捕获解析 JWT 失败后产生的错误
app.use((err, req, res, next) => {
  // 这次错误是由 token 解析失败导致的
  if (err.name === 'UnauthorizedError') {
    return res.send({
      status: 401,
      message: '无效的token',
    })
  }
  res.send({
    status: 500,
    message: '未知的错误',
  })
})

// 调用 app.listen 方法,指定端口号并启动web服务器
app.listen(8888, function () {
  console.log('Express server running at http://127.0.0.1:8888')
})

你可能感兴趣的:(javascript,前端,node.js)