Node.js
Node架构
Natives modules
- 当前层由 JS 实现
- 提供应用程序可直接调用库
- JS 无法直接操作底层硬件设置
Builtin modules
底层
- V8: 执行 JS 代码,提供桥梁接口
- Libuv: 事件循环、事件队列、异常IO
- 第三方模块: zlib、 http 等
Node.js 服务端语言
Node.js 异步IO
- IO 是应用程序的瓶颈所在
- 异步IO 提高性能无需原地等待结果返回
- IO 操作属于操作系统级别,平台都有对应实现
- Nodejs 单线程配合事件驱动架构及 libuv实现 异步IO
Nodejs 的事件驱动架构
事件驱动架构 是 软件开发中的通用模式
Nodejs 单线程
- Nodejs 主线程 是 单线程
- 不适合处理 CPU 密集型计算
Nodejs 应用场景 (适合 IO 密集型任务)
- IO 密集型高并发请求
- 操作数据库提供 API 服务
Nodejs 注意点
- Nodejs 中不能使用 BOM 和 DOM 的 API,可以使用 console 和定时器 API
- Nodejs 中顶级对象 global,也可以用globalThis 访问顶级对象
Buffer
Buffer 缓冲区,是一个类似 Array 的对象,用于表示固定长度的字节序列
- Buffer 就是一段固定长度的内存空间,用于处理二进制数据
特点
- 大小固定
- 性能较好,直接对内存进行操作
- 每个元素大小为 1 字节(byte)
创建 Buffer
// 创建 Buffer
// 1. alloc // 先会清空内存
let buf = Buffer.alloc(10); //
console.log(buf);
// <Buffer 00 00 00 00 00 00 00 00 00 00>
// 2. allocUnsafe
// 生成的数据可能有之前的数据,不会先清空内存
let buf1 = Buffer.allocUnsafe(10);
console.log(buf1);
// <Buffer 00 00 00 00 00 00 00 00 00 00>
// 3. from
let buf3 = Buffer.from('hello')
console.log(buf3);
// <Buffer 68 65 6c 6c 6f>
Buffer 与 字符串的转换
// Buffer 与 字符串的转化
let buf = Buffer.from([105,108,111,118,101,121,111,117])
console.log(buf.toString()) // utf-8
// iloveyou
Buffer 元素读写
let buf = Buffer.from("hello")
console.log(buf)
buf[0] = 96
console.log(buf.toString())
// <Buffer 68 65 6c 6c 6f>
// `ello
fs 模块
- fs 模块可以实现与硬盘的交互
const fs = require("fs")
fs.writeFile('./zuoyouming.txt', '雷猴', err => {
if (err) {
console.log('写入失败')
return
}
})
fs 同步 与 异步
fs 追加写入(适合写入少的场景)
const fs = require("fs")
fs.appendFile("./zuoyouming.txt", "xiaohuozhi",(err)=>{
if(err){
console.log("Failed to append")
return
}
console.log("Success")
})
appendFileSync
fs 流式写入 (适合写入频繁的场景)
const fs = require('fs');
const ws = fs.createWriteStream('first.txt')
ws.write('nihao\r\n')
ws.write('nihao\r\n')
ws.write('nihao\r\n')
ws.write('nihao\r\n')
fs 读取文件
const fs = require('fs');
fs.readFile('./first.txt', 'utf-8',(err,data)=>{
if(err){
console.log(err);
return
}
console.log(data.toString())
})
//
const fs = require('fs');
let data = fs.readFileSync('./first.txt')
console.log(data.toString());
fs 流式读取
(一块一块读取的)
const fs = require('fs');
const rs = fs.createReadStream('./1.mp3')
rs.on('data', chunk => {
console.log(chunk)
})
// end 事件 会 默认执行
// rs.on('end', ()=>{
// console.log('end')
// })
fs 复制文件
/**
* 需求:
* 复制文件
*/
// 使用 readFile 和 writeFile
const fs = require('fs');
fs.readFile('./1.mp3', (err, data)=>{
if(err){
console.log('Error reading')
return
}
fs.writeFile('./read1.mp3', data, (err)=>{
if(err){
console.log('Error');
return
}
})
})
// 使用 流读取写入
const fs = require('fs');
const rs = fs.createReadStream('./1.mp3')
const ws = fs.createWriteStream('./c1.mp3')
rs.on('data', chunk => {
console.log(chunk)
if(!chunk){
return
}
ws.write(chunk)
})
fs 文件移动与重命名
// 文件重命名
const fs = require('fs');
// 异步
fs.rename('./1.mp3', './2.mp3', err =>{
if(err){
console.log(err);
return;
}
})
// 同步
renameSync()
// 文件移动
const fs = require('fs');
fs.rename('./2.mp3', './file/2.mp3', err =>{
if(err){
console.log(err);
return;
}
})
fs 文件删除
const fs = require('fs');
// 异步
fs.unlink('./file/2.mp3', err =>{
if(err){
console.log('Unlink Error')
return
}
})
// 同步
unlinkSync(path);
// 方式二
const fs = require('fs');
fs.rm('./file/2.mp3', err =>{
if(err){
console.log('Unlink Error')
return
}
})
rmSync()
fs 文件夹操作
const fs = require('fs');
fs.mkdir('./new', err => {
if(err){
console.log("Error mkdir")
return
}
console.log('Sucessfully')
})
fs.mkdirSync();
// 2. 递归创建文件夹
const fs = require('fs');
// 递归创建
fs.mkdir('./new/a/b/c', {recursive: true}, err => {
if(err){
console.log("Error mkdir")
return
}
console.log('Sucessfully')
})
// 3. 读取文件夹
const fs = require('fs');
// 读取文件夹
fs.readdir('./', (err,data) => {
if (err) {
console.log('error')
return
}
console.log(data)
})
// 4. 删除文件夹
const fs = require('fs');
fs.rmdir('./new/a', err =>{
if(err){
console.log('error')
return
}
console.log('Successfully')
})
// 递归删除文件夹
const fs = require('fs');
fs.rmdir('./new', {recursive: true}, err =>{
if(err){
console.log('error')
return
}
console.log('Successfully')
})
fs 查看资源状态
const fs = require('fs');
fs.stat('./first.txt', (err, data) => {
if(err){
console.log('Error')
return
}
console.log(data)
})
let data = fs.statSync('./first.txt')
console.log(data)
fs 路径
- 相对路径
- 绝对路径
fs 相对路径的 Bug
// 相对路径的参照物: 命令行的工作目录
__dirname
- 表示这个文件的所在目录的绝对路径
fs 批量重命名
const fs = require('fs');
// 批量重命名
const files = fs.readdirSync('./new');
// console.log(files)
let dir = `${__dirname}/new/`
let i = 0
files.forEach(item => {
console.log(item)
let newName = (item.split('.')[0] = i++) + '.' + item.split('.')[1]
reName(dir, item, newName)
})
// 重命名
function reName(dir, filename, Name){
fs.rename(`${dir}/${filename}`, `${dir}/${Name}`, err => {
if(err) throw err
console.log('Successfully')
})
}
path 模块
HTTP 请求报文
请求行
GET www.baidu.com/ HTTP/1.1
-
请求方法
-
URL
- 协议名
- 主机名
- 端口号
- 路径
- 查询字符串
-
HTTP 版本号
请求头
请求体
HTTP 响应报文
响应头
http 模块
const http = require('http')
const server = http.createServer((req, res) => {
res.end("hello world")
});
server.listen(8088, ()=>{
console.log("listening on 8088")
});
HTTP 注意事项
HTTP 响应文件内容
const http = require('http')
const fs = require('fs')
const server = http.createServer((req, res) => {
let html = fs.readFileSync('./file/index.html')
res.end(html)
});
server.listen(8088, ()=>{
console.log("listening on 8088")
});
网页资源加载基本过程
- html
- css
- js
- 图片等
HTTP 响应练习扩展
// 识别不同请求返回对应文件
const http = require('http')
const fs = require('fs')
const server = http.createServer((req, res) => {
// 获取 请求路径
let {pathname} = new URL(req.url, 'http://localhost:8088')
console.log(pathname)
let path;
if(pathname === '/'){
path = __dirname + '\\file\\index.html'
}else if(pathname === '/index.css'){
path = __dirname + '\\file\\index.css'
}else if(pathname === '/index.js'){
path = __dirname + '\\file\\index.js'
}else{
res.end('404')
}
let result = fs.readFileSync(path)
res.end(result)
});
server.listen(8088, ()=>{
console.log("listening on 8088")
});
静态资源 和 动态资源
搭建静态资源服务
静态资源目录网站资源目录
网页中的 URL
绝对路径
相对路径
设置 MIME 类型
媒体类型 Multipurpose Internet Mail Extensions, 用来表示文档、文件 或 字节流的性质和格式
解决乱码问题
-
- 设置响应头 (优先级更高)
-
- 设置 meta 标签
完善资源请求错误处理
GET 和 POST 请求场景
请求区别
Node 模块化
将一个复杂的程序文件依据一定规则(规范)拆分成多个文件的过程 叫做 模块化
好处
- 防止命名冲突
- 高复用性
- 高维护性
模块暴露数据
注意
// require 返回的结果是 module.exports 的值
Nodejs 导入模块
// require
注意
导入文件夹的情况
如果导入的路径是一个文件夹,会首先检测该文件夹下的package.json 中 main 的属性指向的文件
如果 main 属性不存在,或 package.json 不存在,则会检测文件夹 index.js 和 index.json
如果还是没有,就报错
文件结构
- pack
- module
- app.js
- package.json
- main.js
- module
// package.json
{
"main": "./app.js"
}
// app.js
module.exports = '我是一个模块'
// main.js
// 导入
const m = require('./module')
console.log(m) // 我是一个模块
require 导入模块基本流程
require 伪代码
function require(file){
// 1. 将相对路径转换为绝对路径,定位目标文件
let absolutePath = path.resolve(__dirname, file)
// 2. 缓存检测
if(caches[absolutePath]){
return caches[absolutePath]
}
// 3. 读取文件的代码
let code = fs.readFileSync(absolutePath).toString()
// 4. 包裹为一个函数
let module = {}
let exports = module.exports = {}
(function(exports, require, module, __filename, __dirname){
const test = {
name: "nihao"
}
module.exports = test
console.log(arguments.callee.toString())
})(exports, require, module, __filename, __dirname)
// 5. 缓存结果
caches[absolutePath] = module.exports
// 6. 返回缓存结果
return module.exports;
}
注意
const m = require('./m.js')
const m1 = require('./m.js')
// 结果只输出一次,因为有缓存
CommonJS 规范
Nodejs 是实现了 CommonJS 模块化规范。
npm 初始化包
npm init
每一个包都要有 package.json 文件
包 的配置文件
npm 搜索包
开发依赖 和 生产依赖
{
"name": "npmtest",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "guibin",
"license": "ISC",
// 生产环境 npm i -S jquery
"dependencies": {
"jquery": "^3.7.0"
},
// 开发环境 npm i -D less
"devDependencies": {
"less": "^4.2.0"
}
}
npm 全局安装
修改 windows 执行策略
- 选 A
环境变量 Path
npm 安装指定版本包
// 格式
npm i <包名@版本号>
// 例子
npm i jquery@1.11.2
npm 配置命令别名
nvm 介绍 使用
用于管理 node 的版本管理工具,方便切换版本
nvm 安装、卸载与使用(详细步骤)
express 框架
express 路由
路由确定了应用程序如何响应客户端对特定端点的请求
- 一个路由的组成有
请求方法,路径和回调函数组成
路由的使用
// 语法
app.<method>(path, callback)
// 1. 导入 express
const express = require('express')
// 2. 创建应用对象
const app = express()
// get 请求
app.get('/home', (req, res)=>{
res.end('hello')
})
// post 请求
app.post('/home', (req, res)=>{
res.end('home')
});
// all 所有,只要是 /test 这个路径就匹配
app.all('/test', (req, res)=>{})
// * 通配符
app.all('*', (req, res)=>{})
// 4. 监听端口,启动服务
app.listen(3000, ()=>{
console.log('listening on port 3000')
})
获取请求报文参数
// 获取请求的路由规则
app.get('/request', (req, res) => {
// 1. 获取报文的方式与原生 HTTP 获取方式是兼容的
console.log(req.method)
console.log(req.url)
console.log(req.httpVersion)
console.log(req.headers)
// express 独有的获取报文方式
// 获取查询字符串
console.log(req.query)
// 获取指定的请求头
console.log(req.get('host'))
res.send('请求报文参数获取')
})
获取路由参数
// 获取请求的路由规则
app.get('/:id.html', (req, res) => {
console.log(req.params.id)
res.end('hello')
})
路由参数练习
通过请求找歌手数据
- package
- Data
- data.json
- index.js
- package.json
- package-lock.json
- Data
// index.js
// 1. 导入 express
const express = require('express')
const fs = require('fs')
const {singers} = require('./Data/data.json')
// 2. 创建应用对象
const app = express()
// 获取请求的路由规则
app.get('/singer/:id.html', (req, res) => {
let {id} = req.params
let result = singers.find(item => {
if(item.singer_name === id) {
res.setHeader('Content-Type', 'application/json; charset=utf-8')
res.end(JSON.stringify(item))
}
})
})
// 4. 监听端口,启动服务
app.listen(3000, ()=>{
console.log('listening on port 3000')
})
// data.json
{
"singers":[
{
"singer_name": "周杰伦",
"singer_pic": "pic_周杰伦",
"other_singer_name": "Jay_Chou"
},
{
"singer_name": "李荣浩",
"singer_pic": "pic_李荣浩",
"other_singer_name": "Jay_Chou"
},
{
"singer_name": "张杰",
"singer_pic": "pic_张杰",
"other_singer_name": "Jay_Chou"
},
{
"singer_name": "陈奕迅",
"singer_pic": "pic_陈奕迅",
"other_singer_name": "Eason"
},
{
"singer_name": "林俊杰",
"singer_pic": "pic_林俊杰",
"other_singer_name": "Jay_Chou"
}
]
}
响应设置
express 中间件
1. 什么是中间件
本质: 回调函数
中间件函数 可以像路由回调一样访问 请求对象(request) 响应对象(response)
2. 中间件的作用
中间件的作用 就是 使用函数封装公共操作,简化代码
3. 中间件类型
- 全局中间件
- 路由中间件
定义全局中间件
/**
* 全局中间件
* 记录每个请求的 url 和 IP 地址
*/
const express = require('express')
const app = express()
const fs = require('fs')
const path = require('path')
// 声明中间件函数
function recordMiddleware(req, res, next) {
// 获取 url 和 ip
let {url, ip} = req
// 将信息保存在文件中 access.log
fs.appendFileSync(path.resolve(__dirname, './access.log'),`${url} ${ip} \r\n`)
// 调用 next
next()
}
// 使用中间件函数
app.use(recordMiddleware)
app.get('/home', (req, res) => {
res.send('home')
})
app.get('/admin', (req, res) => {
res.send('admin')
})
app.get('*', (req, res) => {
res.send('*')
})
app.listen(3000, (req, res) => {
console.log('listening on port 3000')
})
路由中间件实践
/**
* 路由中间件
* 针对 /admin /setting 的请求要求 URL 携带 code = 521 参数,如果没有携带提示 [暗号错误]
*/
const express = require('express')
const app = express()
const path = require('path')
app.get('/home', (req, res) => {
res.send('home')
})
// 设置路由中间件
let checkCodeMiddleware = (req, res, next) =>{
// 判断 URL 中是否 code 参数为 521
if(req.query.code === '521'){
next()
}else{
res.send('暗号错误')
}
}
app.get('/admin', checkCodeMiddleware, (req, res) => {
res.send('admin')
})
app.get('/setting', checkCodeMiddleware, (req, res) => {
res.send('setting')
})
app.get('*', (req, res) => {
res.send('*')
})
app.listen(3000, (req, res) => {
console.log('listening on port 3000')
})
静态资源中间件
- package
- public
- css
- index.css
- index.html
- index.js
- public
// index.js
// 1. 导入 express
const express = require('express')
// 2. 创建应用对象
const app = express()
// 静态资源中间件设置
app.use(express.static(__dirname + '/public'))
// 4. 监听端口,启动服务
app.listen(3000, ()=>{
console.log('listening on port 3000')
})
注意点
获取请求体数据
/**
* 搭建 HTTP 服务
* GET /login 显示表单网页
* POST /login 获取表单中的 [用户名] 和 [密码]
*/
// 1. 导入 express
const express = require('express')
const bodyParser = require('body-parser')
// 2. 创建应用对象
const app = express()
// 静态资源中间件设置
app.use(express.static(__dirname + '/public'))
// 解析 JSON 格式的请求体的中间件
const jsonParser = bodyParser.json()
// 解析 querystring 格式请求体的中间件
const urlencodedParser = bodyParser.urlencoded({extended:false})
app.get('/login', (req, res) => {
res.sendFile(__dirname + '/public/login/login.html')
})
app.post('/login', urlencodedParser, (req, res) => {
console.log(req)
let {username, password} = req.body
console.log(username, password)
res.send(`${username}: ${password}`)
})
// 4. 监听端口,启动服务
app.listen(3000, ()=>{
console.log('listening on port 3000')
})
// login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>login</title>
</head>
<body>
<div>
<h1>login</h1>
<form action="/login" method="post">
<span>
<p>username</p><input name="username" type="text">
</span>
<span>
<p>password</p><input name="password" type="password">
</span>
<span>
<button>login</button>
</span>
</form>
</div>
</body>
</html>
防盗链
防止外部网站盗用网站资源
防盗链实践
/**
* 图片防盗链
*/
// 1. 导入 express
const express = require('express')
// 2. 创建应用对象
const app = express()
// 声明中间件
app.use((req,res,next) => {
// 检测请求头中的 referer 是否为 127.0.0.1
// 获取 referer
let referer = req.get('referer')
console.log(referer)
if(referer){
// 实例化
let url = new URL(referer)
let hostname = url.hostname
if(hostname !== '127.0.0.1'){
res.status(404).send('<h1>404</h1>')
return
}
}
next()
})
// 静态资源中间件设置
app.use(express.static(__dirname + '/public'))
// 4. 监听端口,启动服务
app.listen(3000, ()=>{
console.log('listening on port 3000')
})
路由模块化
// index.js
// 1. 导入 express
const express = require('express')
const index = require('./public/routes/index')
// 2. 创建应用对象
const app = express()
app.use(index)
// 静态资源中间件设置
app.use(express.static(__dirname + '/public'))
// 4. 监听端口,启动服务
app.listen(3000, ()=>{
console.log('listening on port 3000')
})
// routes/index.js
const express = require('express');
const router = express.Router();
router.get('/', function (req, res){
res.send('home')
})
router.get('/home', function (req, res){
res.send('home')
})
router.get('/about', function (req, res){
res.send('about')
})
module.exports = router;
模板引擎(EJS)
模板引擎是分离 用户界面 和 业务数据 的一种数据
下载
npm i ejs --save
ejs 初体验
// 导入 ejs
const ejs = require('ejs');
const fs = require('fs');
// 字符串
let china = '中国'
let str = fs.readFileSync('./01_模板渲染.html').toString()
// 使用 ejs 渲染
let result = ejs.render(str, {china:china})
console.log(result)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>
我爱你 <%= china %>
</h1>
</body>
</html>
ejs 列表渲染
// 导入 ejs
const ejs = require('ejs');
let xiyou = ['孙悟空','唐僧','猪八戒','沙悟净']
// 使用 ejs 渲染
let result = ejs.render(
`<ul>
<% xiyou.forEach(item => { %>
<li><%= item %></li>
<% }) %>
</ul>`
, {xiyou: xiyou})
console.log(result)
ejs 条件渲染
// 导入 ejs
const ejs = require('ejs');
let isLogin = false;
// 使用 ejs 渲染
let result = ejs.render(`
<% if(isLogin){ %>
<span>True</span>
<% } else { %>
<span>False</span>
<% } %>`,
{isLogin: isLogin})
console.log(result)
express 中使用ejs
// index.js
const express = require('express')
const path = require('path')
const app = express()
// 1. 设置模板引擎
app.set('view engine', 'ejs')
// 2. 设置模板文件存放位置
// 模板文件: 具有模板语法的内容的文件
app.set('views', path.resolve(__dirname, './views'))
app.get('/', (req, res) => {
let title = '你好啊啊啊'
// res.render(模板的文件名,数据)
res.render('home', {title})
})
app.listen(3000, ()=>{
console.log('listening on 3000')
})
// home.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><%= title %></title>
</head>
<body>
<h2>测试</h2>
</body>
</html>
express-generator (生成器)
通过应用生成器工具快速创建一个应用的骨架
npm i -g express-generator
文件上传报文
<!-- enctype 文件上传必须属性 -->
<form action="/portrait" method="post"
enctype="multipart/form-data">
用户名: <input type="text" name="username"><br>
头像: <input type="file" name="portrait"><br>
<hr>
<button>提交</button>
</form>
formidable (处理文件请求)
接口的介绍
前后端通讯的桥梁
RESTful API
json-server 工具
会话控制
Cookie
cookie 是 HTTP 服务器发送到用户浏览器并保存在本地的一小块数据
- cookie 是保存在浏览器端的一小块数据
- cookie 是按照域名划分保存的
特点
浏览器向服务器发送请求时,会自动将 当前域名下 可用的 cookie 设置在请求头中,然后传递给服务器
浏览器操作 cookie
- 禁用 cookie
- 删除 cookie
- 查看 cookie
express 设置 Cookie
const express = require('express')
const cookieParser = require('cookie-parser')
const app = express()
app.use(cookieParser())
// 设置 cookie
app.get('/set-cookie', (req,res)=>{
// res.cookie('name','zhansan') // 会在浏览器关闭时删除
res.cookie('name','zhansan', {maxAge: 60 * 1000}) // 会在浏览器关闭时删除
res.cookie('age',23) // 会在浏览器关闭时删除
res.send('home')
})
// 删除 cookie
app.get('/rm-cookie', (req,res)=>{
res.clearCookie('name')
res.send('del Successfully')
})
// 获取 cookie
app.get('/get-cookie', (req,res)=>{
console.log(req.cookies)
res.send('read')
})
app.listen(3000, () => {
console.log('listening on port 3000')
})
Session
-
session 是什么 是保存在 服务器端的一块数据, 保存当前访问用户的相关信息
-
作用 实现会话控制,可以识别用户的身份,快速获取当前用户相关信息
-
运行流程
Session 中间件
const express = require('express')
const session = require('express-session')
const MongoStore = require('connect-mongo')
const app = express()
app.use(
session({
name: 'sid', // 设置 cookie 的 name 默认值是 connect.id
secret: 'atguigu', // 参与加密的的字符串 (签名)
// 是否为每次请求都设置一个 cookie 用来 存储session 的 id
saveUninitialized: false,
// 是否每次请求时都重新保存 session
resave: false,
store: MongoStore.create({
mongoUrl: 'mongodb://localhost:27017/',
}),
cookie: {
// 开启后前端无法通过 JS 操作
httpOnly: true,
// sessionId 的超时时间
maxAge: 1000 * 60 * 5, // 5 分钟
}
})
)
app.get('/', (req,res)=>{
res.send('home')
})
// 登录
app.get('/login', (req,res)=>{
// username password
if(req.query.username === 'admin' && req.query.password === '123456'){
// 设置 session
req.session.username = 'admin'
req.session.uid = 'sdfsa'
res.send('login success')
}else{
res.send('login fail')
}
})
// session 读取
app.get('/cart', function(req, res){
if(req.session.username){
res.send('login success cart')
}else{
res.send('还没登录...')
}
})
// session 销毁
app.get('/logout', (req, res) => {
req.session.destroy(()=>{
res.send('logout success')
})
})
app.listen(3000, () => {
console.log('listening on port 3000')
})
Session 与 Cookie 的区别
CSRF 跨站请求伪造
Token
JWT
JWT (JSON Web Token) 是目前最流行的跨域认证解决方案,可用于基于 token 的身份认证
实例
// 导入 jwt
const jwt = require('jsonwebtoken');
// // 创建 token
// // let token = jwt.sign(用户数据,加密字符串,配置对象)
// let token = jwt.sign({
// username: 'zhangsan',
// }, 'jsonegg', {
// expiresIn: 60 // 单位 s
// })
// console.log(token)
let token = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InpoYW5nc2FuIiwiaWF0IjoxNjkzMzgyMjU2LCJleHAiOjE2OTMzODIzMTZ9.rmvbhFJo3CXv4rjqSJUhis_L9vHiqk-2zJsV0xpdaAI'
// 校验 token
jwt.verify(token, 'jsonegg', (err, data)=>{
if(err){
console.log(err);
}else{
console.log(data);
}
})
- 校验成功 (解析数据)
- 校验失败 (超时)