node.js基本知识学习笔记

node.js是基于v8引擎的javascript运行时环境

node.js安装路径 https://nodejs.org/en/

node.js基本命令

node js文件        #《在node.js环境中执行javascript代码 例如node aaa.js》
npm install 包完整名称 / npm i 包完整名称    #《在项目中安装指定名称的包  例如node install moment 。当安装多个包时,npm i jquery moment 包和包之间用空格分隔》
npm init -y   #《在执行命令的目录中,快速创建package.json文件(一般在新建了项目文件夹,但还没有写代码时,执行该命令。运行npm install安装包时,npm会自动把包的名称和版本号记录到package.json文件中)。》
npm install   #《该命令会先读取package.json中的dependencies节点,读取到记录的依赖包名称和版本后,npm会将这些包一次性全部下载到项目中》
npm uninstall 包完整名称   #《卸载包 例如npm uninstall moment》
npm install   #包名 -D/npm install 包名 --save-dev 《将包记录到devDependencies节点中。》
npm i nrm -g   #《将**nrm**安装为全局可用工具  (注:nrm是切换下包时镜像源的工具)》
nrm ls    #《查看所有可用的镜像源》
nrm use taobao   #《将下包的镜像源切换为淘宝镜像。》
npm install 包名-g    #《安装全局包》
npm uninstall 包名 -g    #《卸载全局包》
npm login   #《在命令行中登录npm》
npm publish   #《将包发布到npm上(首先要切换到包的根目录,然后执行命令)》
npm unpublish 包名 --force   #《从npm删除已经发布的包》
nodemon js文件名     #《自动重启j 例如nodemon aaa.js》
npm i moment@2.22.2     #《@是下载指定版本的包》

npx ng generate component 组件名  #生成anuglar组件。npx是第三方可执行文件的执行工具,可以执行node_moudules/.bin目录下的可执行文件

模块

fs文件系统模块

const fs = require('fs') //导入fs文件系统模块
fs.readFile() //读取指定文件中的内容
fs.writeFile() //向指定文件中写入内容
// 读取
fs.readFile('./1.txt', 'utf8', (err, buff) => {
	console.log('err', err)
	console.log('buff', buff)
})
// 默认写入的编码格式是utf8
// 注意如果files文件夹不存在,则写入失败
// wiritFile写入同一个文件时,新写入的内容会覆盖之前旧的内容
fs.writeFile('/files/2.txt', 'hello', (err) => {
	console.log('err:', err)
})

// 注意 ./和…/开头的相对路径,会以执行node命令时所处的目录,动态拼接处被操作文件的完整路径。所以建议用__dirname

//例如
fs.writeFile(__dirname + '/2.txt', 'hello', (err) => {
	console.log('err:', err)
})

path路径模块

const path = require('path') //导入fs模块
path.join() //将多个路径片段拼接成一个完整的路径字符串
path.basename() //从路径字符串中将文件名解析出来
path.extname() // 获取路径中的文件扩展名
//路径字符串拼接
const paths=path.join(__dirname,'/files/1.txt')
//获取path中的文件名
const fpath ='/a/b/index.html
const paths = path.basename(fpath) // 输出index.html
const pathss = plath.basename(fpath,'.html') // 输出index,会去掉后缀
const pathse =path.extname(fpath) //输出.html

http web服务模块

const http = require('http') //导入http模块
const server = http.createServer() //创建一个web实例
// 为服务绑定一个request事件,必须是request
server.on('request', (req, res) => {
    const url = req.url
    const method = req.method
    const str = `请求路径:${url}请求方法:${method}`
    // 设置响应头解决中文乱码
    res.setHeader('Content-Type', 'text/html; charset=utf-8')
    // 响应给客户端
    res.end(str)
})
//启动服务并监听80端口
server.listen(80, () => {
    console.log('running')
})

加载模块

  • 模块分为内置模块(fs,path,http)、自定义模块(用户写的js文件)、第三方模块。
  • 模块作用域:模块中定义的变量和方法等成员,只能在当前模块中访问。
// 使用require()方法加载其他模块时,会执行被加载模块中的代码
require()
//加载内置模块
const fs = require('fs')
// 加载自定义模块 
// 注意在外界使用require导入一个自定义模块时得到的成员,就是要导入的模块(customers.js)中通过module.exports指向的那个对象,module.exports默认是空对象 即exports: {}
const fs = require('./customers.js')
// 注意在使用require加载自定义模块时,可以省略后面的.js的后缀名
const fs = require('./customers')

module对象

  • 每个自定义js模块中都有一个module对象,module对象中存储了和当前模块有关的信息
console.log(module)

在这里插入图片描述

// 注意其中module对象中的exports属性可以对外共享成员,让模块内的成员可以被外界访问到
// 向module.exports对象上挂载username属性,即对外共享username属性
module.exports.username = 'zhangsan'
// 向module.exports对象上挂载sayHello方法,即对外共享username方法
module.exports.sayHello = function (){}
//注意 使用require()方法导入模块时,导入的结果,永远以module.exports指向的对象为准。例如下面将exports重新指向了新的对象
module.exports = {nickname = 'liwu'}
//
const hello = require('hello')
say = function(){}
module.exports = {
    say,             //对外暴露函数say
    ...hello         //...是展开运算符 是将hello对象中每个属性进行展开,然后交给module.exports进行存储
}

exports对象

  • 默认情况下exports和module.exports指向同一个对象
// 结果是true
console.log(exports === module.exports)
  • 使用require()方法导入模块时,导入的结果,永远以module.exports指向的对象为准

在这里插入图片描述

CommonJSm模块化规范

  • 每个模块内部,module变量代表当前模块
  • moudle变量是个对象,它的exports属性(module.exports)是对外的接口
  • 加载某个模块时,其实是加载该模块的module.exports属性,require方法用于加载模块

包(第三方模块)

  • 第三方模块又叫做包
  • 包是基于内置模块封装出来的
  • 搜索包的网站 https://www.npmjs.com/
  • 下载包的地址 https://registry.npmjs.org

在这里插入图片描述

安装第三方包

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • node_modules目录:用来存放所有已经安装到项目中的包(即都是项目包),require()导入第三方包时就是从这个目录中查找并加载的。
  • package-lock.json文件:用来记载每个包的下载信息。 注意:npm install默认是下载最新版本的包
npm i moment@2.22.2    # 下载指定版本的包

package.json文件

  • package.json是包管理配置文件,存放到项目的根目录中,用来记录和项目有关的一些配置(例如项目安装了哪些包)。

  • devDependencies节点,某些包只在项目开发阶段用(开发依赖包),项目上线之后不用,就记录到devDependencies节点中

  • dependencies节点,某些包在项目开发阶段用和项目上线阶段都用(核心依赖包),就记录到dependencies节点中

更改下包的镜像源

#注意 npm默认的下包服务地址是国外的
# 查看当前下包镜像源
npm config get registry
# 改成淘宝npm镜像
npm config set registry=https://registry.npm.taobao.org/
  • 或者用nrm工具

在这里插入图片描述

  • 使用npm install 时 如果提供了 -g参数 则会把包安装为全局包

在这里插入图片描述

  • 安装i5ting_toc工具可以将.md转换为html
# 安装i5ting_toc包
npm install i5ting_toc -g
# 转换文件
i5ting_toc -f 要转换的md文件路径 -o

规范的包结构

  • 包必须以单独的目录存在
  • 包的根目录必须要包含package.json这个包管理配置文件
  • package.json中必须包含name,version,main这三个属性,分别代表包名,版本号,包的入口

下载的包根目录下的package.json文件中,有一个 main属性,main属性是包的入口,当用require()导入第三方模块时,内部就是加载main属性所指向的文件。
在这里插入图片描述
在这里插入图片描述

模块的加载机制

  • 模块在第一次加载后会被缓存,即多次调用require()不会导致模块代码被执行多次。
  • 内置模块加载优先级最高,如果node_modules中也有fs模块那么require(‘fs’)加载的始终都是内置的fs模块。
  • require()加载自定义模块时,必须指定以./或…/开头的路径标识符,如果没指定,node会当作内置模块或第三方模块进行加载。

在这里插入图片描述

  • node.js会从当前模块的父目录开始,尝试从node_modules文件夹中加载第三方模块,如果没找到对应的,则移动到再上一层的父目录中进行加载,直到文件系统的根目录。
    在这里插入图片描述
    在这里插入图片描述

Express框架

  • 是基于内置http模块进一步封装出来的Web开发框架。
# 安装 express包
npm i express
// 导入express模块
const express = require('express')
//创建web服务器
const app = express()
//监听get请求,并且URL为/
app.get('/', function (req, res) {
  //req.query默认是个空对象,客户端请求时,带有?name=zhangsan类似的请求参数,req.query.name就能访问到
  const query = req.query
  //把内容响应给客户端
  res.send('Hello world!')
});
//监听post请求。:id 是动态URL参数
app.post('/:id', function (req, res) {
   // req.params默认是个空对象,能获取请求中的动态URL参数
   const params= req.params
   res.send({name: 'zhangsan'})
});
//调用app.listen启动服务器,并监听80端口
app.listen(80, ()=>{
    console.log('success')
});

托管静态资源

// 托管静态资源目录,public就是静态资源的文件夹,之后就可以访问public下的资源了
//注意 存放静态文件的目录名不会出现在URL中,如http://localhost/index.html访问的就是public文件夹下的index.html文件,但路径中没有public
app.use(express.static('public'))
// 托管多个静态资源目录,访问静态资源目录时,express.static会根据目录添加的顺序查找所需的文件
//即请求路径 http://localhost/index.html,如果public1下有index.html文件就先访问public1中的,public1中没有则再看public2中有没有,如果有就访问。
app.use(express.static('public1'))
app.use(express.static('public2'))
//挂载路径前缀
app.use('public',express.static('public')) 请求路径 http://localhost/public/index.html

路由

// 路由分三部分组成,请求类型,请求的URL,处理函数。路由匹配安装定义的先后顺序进行匹配
// app.METHOD(PATH,HANDLER)
// 挂载路由
app.post('/', function (req, res) {})

nodemon工具

# 安装nodemon
npm install -g nodemon
nodemon 1.js  #出现下面错误

在这里插入图片描述
解决方法:用管理者模式在powershell中输入

set-ExecutionPolicy RemoteSigned

在这里插入图片描述

路由模块化

  1. 创建路由模块abc.js
const express = require('express')
// 1.创建路由对象
const router = express().Router()
// 2.挂载get 路由
router.get('/', function (req, res) {
  res.send('Hello world!')
});
// 3.向外导出路由对象
module.exports = router
  1. 导入路由模块
const express = require('express')
const app = express()
// 导入路由模块
const userRouter = require('./abc.js')
// 注意app.use(中间件函数)的作用是,注册全局中间件。express.static()、express.Routera()都是中间件
// 注册路由模块
app.use(userRouter)
//挂载路径前缀
app.use('/router',userRouter)

中间件

  • Middleware 指业务流程的中间处理环节,上一级的输出作为下一级的输入。
  • 当一个请求到达express服务器后,可以连续调用多个中间件,对请求进行预处理操作。
  • express中间件本质上就是function处理函数,中间件形参列表中必须包含next参数,而路由处理函数只包含req和res。
    在这里插入图片描述
  • next()函数是实现多个中间件连续调用的关键,表示把流传关系转交给下一个中间件或路由。

在这里插入图片描述

定义全局生效中间件
// 定义中间件函数
const method1 = function (req, res, next) {
    res.send('Hello world!')
    // 中间件业务处理完成后一定要调用next()
    // 表示把流传关系转交给下一个中间件或路由
    next()
}
// 将中间件method1,注册为全局生效的中间件
app.use(method1)
  • 全局生效的中间件:客户端发起请求到达服务器后都会触发的中间件,即全局生效的中间件
  • 多个中间件之间可以共享同一份reqres,即在上游的中间件中为req添加属性或方法,下游的中间件或路由就能获取到添加的属性或方法。
app.use(function (req, res, next) {
	// 在上游的中间件中,为req挂载自定义属性startTime
	req.startTime = Date.now()
    next()
})
app.get('/', function (req, res) {
  //下游的路由就能获取到自定义属性startTime
  console.log(req.startTime)
});
  • 可以使用app.use()连续定义多个全局生效中间件,请求会按照中间件定义的先后顺序依次执行
app.use(function (req, res, next) {
	console.log('调用第一个全局中间件')
    next()
})
app.use(function (req, res, next) {
	console.log('调用第二个全局中间件')
    next()
})
//请求这个路由会依次触发上面两个全局中间件
app.get('/', function (req, res) { 
  console.log('')
});
定义局部生效中间件
  • 不使用app.use()定义的中间件,就是局部中间件
// 定义中间件函数
const method1 = function (req, res, next) {
    res.send('调用第一个局部中间件')
    next()
}
const method2 = function (req, res, next) {
    res.send('调用第二个局部中间件')
    next()
}
// 只有请求路由/user,局部中间件才会生效
app.get('/user', method1 , function (req, res) { 
  console.log('')
});
// 请求路由/,中间件不会生效
app.get('/', function (req, res) { 
  console.log('')
});

// 定义多个局部生效中间件,顺序是method1-->method12-->function (req, res)
app.get('/user', method1, method2 , function (req, res) { console.log('')});
app.get('/user', [method1, method2] , function (req, res) { console.log('')});
  • 要在路由之前注册或定义中间件
app.get('/user', method1, function (req, res) {
    console.log('7777')
});
// 在路由/user之后定义中间件,这是错误的
const method1 = function (req, res, next) {
    console.log('调用第一个局部中间件')
    next()
}
app.get('/user2', function (req, res) {
    console.log('7777')
});
// 在路由/user2之后注册中间件,这也是错误的
app.use(method1)
中间件分类
  • 应用级别的中间件

通过app.use()、app.get()、app.post(),绑定到app实例上的中间件,叫做应用级别的中间件。

// 应用级别的中间件(全局中间件)
app.use(function (req, res, next) {
	console.log('应用级别的中间件(全局中间件)')
    next()
})
// 应用级别的中间件(局部中间件)
app.get('/user', method1 , function (req, res) { 
  console.log('应用级别的中间件(局部中间件)')
});
  • 路由级别的中间件

绑定到express.Router(),即绑定到router实例上的中间件,叫做路由级别的中间件。

const app = express()
const router = express().Router()
// 路由级别的中间件
router.use('/', function (req, res, next) {
  console.log('路由级别的中间件')
});
app.use(router)
  • 错误级别的中间件

作用:用来捕获整个项目中发生的异常错误,错误级别中间件中的function处理函数中,必须有4个形参分别是(err,req,res,next),
错误级别中间件必须注册在所有路由之后

app.use('/user',function (req, res) {
	throw new Error('mistake') // 抛出错误
	console.log('success') // 不会执行
})
// 错误级别的中间件,可以捕获整个项目中发生的异常错误,防止程序崩溃,例如捕获上面的mistake
app.use(function (err, req, res, next) {
	console.log('错误级别的中间件')
    res.send(err.messge)
})
  • Express内置的中间件
    ①express.static()快速托管静态资源,例如HTML、图片、CSS样式等
    ②express.json()解析json格式的请求体数据
    ③express.urlencoded()解析URL-encoded格式的请求体数据,【urlencoded格式】又叫form格式,或者是x-www-form-urlencoded格式。表单格式是由键值对组成。键和值之间用=。多个键值对之间用&。例如:name=ZhangSan&age=16
//配置解析application/json格式数据的内置的中间件,将解析出的数据挂载到req.body
app.use(express.json())
//配置解析application/x-www-form-urlencoded格式数据的内置的中间件,将解析出的数据挂载到req.body
app.use(express.urlencoded({extended: false}))

app.post('/user', function (req, res) {
	// 如果不配置解析请求体数据的中间件,则req.body是undefined
	// req.body默认是undefined,能获取请求中json格式和URL-encoded格式的请求体数据
	const body= req.body
	res.send(body)
});
  • 第三方中间件
    例如:body-parser

自定义中间件

// node内置模块,用来处理查询字符串
const qs = require('querystring')
// 创建自己的中间件函数并且挂载
app.use((req,res,next)=>{
    // 定义一个变量存储客户端字符串
    let str=''
    // 当客户端向服务器发送数据,会触发data事件,监听req的data事件。
    req.on('data',(chunk)=>{
        str+=chunk
    })
    // 当请求体数据接收完毕后,会触发end事件,监听req的end事件。
    req.on('end',()=>{
        console.log(str)
        // 利用内置模块的parser(),将查询的字符串解析成对象
        const body=qs.parse(str)
        // 进行数据对象的挂载
        req.body=body
        console.log(body)
        // 注意此处next一定要在end中
        next()
    })
    
})

跨域问题

跨域问题:当前网页的url和请求的目标资源的url之间,协议,域名,端口号不相同,请求失败。
跨域请求的解决方案有:

  • CORS(主流解决方案)
  • JSONP(只支持get请求)

CORS概念:跨域资源共享,由一系列HTTP响应头组成,这些响应体决定浏览器是否阻止前端JS代码跨域获取资源。CORS主要是在服务器端进行配置。
浏览器的同源安全策略会默认阻止网页的跨域获取资源,但如果服务器配置了CORS相关的响应头,就可以解除浏览器端的跨域访问限制。
在这里插入图片描述

cors是Express的一个第三方中间件,可以解决跨域问题

# 安装cors中间件
npm install cors
//导入cors模块
const cors = require('cors')
//将cors注册为全局可用的中间件
app.use(cors())
CORS响应头
  • Access-Control-Allow-Orign
// 第二个参数是允许访问该资源的外域URL,http://itcn.cn以外的URL就不能访问。
res.setHeader('Access-Control-Allow-Orign','http://itcn.cn')
// *是通配符,表示允许来自任何域的请求
res.setHeader('Access-Control-Allow-Orign','*')
  • Access-Control-Allow-Headers
// 默认情况下 , CORS仅支持客户端向服务器发送如下的9个请求头
// Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)

// 声明额外的请求头例如(Content-Type请求头和X-Custom-Header请求头),多个请求头之间用,号分割
res.setHeader(' Access-Control-Allow-Headers','Content-Type, X-Custom-Header')
  • Access-Control-Allow-Methods
// 默认情况下 , cors仅支持客户端发起GET , POST ,HEAD 请求
// 只允许POST , GET , DELETE , HEAD请求方法 
res.setHeader('Access-Control-Allow-Methods','POST, GET, DELETE, HEAD')
// 允许所有的HTTP请求方法    
res.setHeader('Access-Control-Allow-Methods','*')    
CORS请求的分类
  • 简单请求:同时满足以下两个条件的请求
    ① 请求方式 : GET , POST ,HEAD三者之一
    ② HTTP头部信息 不超过以下几种字段: 无自定义头部字段,。在9个请求头范围之内{Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type (值仅限于 text/plain、multipart/form-data、application/x-www-form-urlencoded 三者之一)}
  • 预检请求:只要符合任何一个条件的请求
    ① 请求方式:为GET, POST ,HEAD之外的请求
    ② 请求头中包含自定义头部字段
    ③ 向服务器发送了application格式的数据
    预检请求概念:在浏览器与服务器正式通信之前 , 浏览器会发送OPTION请求进行预检 ,以获知服务器是否允许该实际请求 , 所以这一次的OPTION请求称为预检请求 , 服务器成功响应预检请求后 , 才会发送真正的请求 , 并且携带真实数据。

JSONP概念:: 浏览器通过<script>标签的src属性 , 请求服务器上的数据 , 同时服务器返回一个函数的调用 . 这种请求数据的方式叫做JSONP

特点

  • JSONP不属于真正的AJAX请求 , 因为他没有使用XMLHttpRequest这个对象
  • JSONP仅支持GET请求 , 不支持POST , PUT , HEAD等请求
// 如果项目中已经配置了CORS跨域资源共享 , 为了防止冲突 , 必须在配置CORS中间件之前声明JSONP的接口 . 否则JSONP接口会被处理成开启了CORS的窗口
// 优先创建 JSONP 接口[这个窗口不会被处理成CORS 接口]
// 必须在配置 cors 中间件之前,配置 JSONP 的接口
app.get('/api/jsonp', (req, res) => {
  // TODO: 定义 JSONP 接口具体的实现过程
  // 1. 得到函数的名称
  const funcName = req.query.callback
  // 2. 定义要发送到客户端的数据对象
  const data = { name: 'zs', age: 22 }
  // 3. 拼接出一个函数的调用 , 这里面是函数的调用
  // JSON.stringify 方法将某个对象转换成 JSON 字符串
  // 模板字符串:是允许嵌入表达式的字符串,它的写法,以反引号 ` 开头,以反引号 ` 结尾
  const scriptStr = `${funcName}(${JSON.stringify(data)})`
  // 4. 把拼接的字符串,响应给客户端
  // 利用了script标签的只能识别js代码的特性,所以响应的结果必须是函数调用
  res.send(scriptStr)
})
// 再配置CORS中间件 [后续的所有接口,都会被处理成CORS接口]    
app.use(cors())  
// 这是一个开启了CORS 的接口
app.get('/api/get',(req,res)=>{})    

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

// 调用$.ajax()函数 , 提供JSONP的配置选项 , 从而发起JSONP请求
// 4. 为 JSONP 按钮绑定点击事件处理函数
$('#btnJSONP').on('click', function () {
  $.ajax({
    type: 'GET',
    url: 'http://127.0.0.1/api/jsonp',
    dataType: 'jsonp', // 表示请求是jsonp请求
    success: function (res) {
      console.log(res)
    },
  })
})

操作MySQL

# 安装MySQL第三方模块
npm install mysql
// 导入mysql模块
const mysql = require('mysql')
// 与DB建立连接
const db = mysql.createPool({
host: '127.0.0.1',  // 数据库的IP
user: 'root'        // 登录数据库的账号
password: 'root'    // 登录数据库的密码
database: 'db01'    // 要操作的数据库
})
// 执行查询语句
db.query('select * from users',(err,results)=>{
	//查询数据失败
	if(err) return console.log(err.message)
	//返回的results是数组,数组中的每个对象就是查询的表中的每条数据
	console.log(results) 
)

const user = {username:'zhangsan',age:'16'}
// ?是占位符
const sqlStr = 'insert into users (username,age) values (?,?)'
// 执行插入语句,[user.username,user.age]使用数组形式依次为占位符赋值
db.query(sqlStr ,[user.username,user.age],(err,results)=>{
	//插入数据失败
	if(err) return console.log(err.message)
	// 返回的results是对象,affectedRows属性是影响的行数。
	if(results.affectedRows ===1)console.log('插入成功') 
)
// 如果数据对象的每个属性和表中的每个字段一一对应,则可以快速插入数据
const user = {username:'zhangsan',age:'16'}
const sqlStr = 'insert into users set ? '
db.query(sqlStr ,user,(err,results)=>{
	if(err) return console.log(err.message)
	if(results.affectedRows ===1)console.log('插入成功') 
)

const user = {id:1,username:'zhang',age:'10'}
const sqlStr = 'update users set username = ?,age = ? where id = ?'
// 执行更新语句
db.query(sqlStr ,[user.username,user.age,user.id],(err,results)=>{
	//更新数据失败
	if(err) return console.log(err.message)
	// 返回的results是对象,affectedRows属性是影响的行数。
	if(results.affectedRows ===1)console.log('更新成功') 
)
// 如果数据对象的每个属性和表中的每个字段一一对应,则可以快速更新数据
const user = {id:1,username:'zhang',age:'10'}
const sqlStr = 'update users set ? where id = ?'
db.query(sqlStr ,[user, user.id],(err,results)=>{
	if(err) return console.log(err.message)
	if(results.affectedRows ===1)console.log('更新成功') 
)

const id = 1
const sqlStr = 'delete from users where id = ?'
// 执行删除语句
db.query(sqlStr, id, (err,results)=>{
	//删除数据失败
	if(err) return console.log(err.message)
	// 返回的results是对象,affectedRows属性是影响的行数。
	if(results.affectedRows ===1)console.log('删除成功') 
)

session工作原理

Cookie默认不支持跨域访问

在这里插入图片描述
在express项目中安装express-session中间件

// 安装express-session第三方模块
npm install express-session
// 导入session中间件
var session = require('express-session')
// 注册中间件
app.use(session({
	secret: 'word', // 可以为任意字符串,对session进行加密
	resave: false,  // 固定写法
	saveUninitialized: true  // 固定写法
}))

当express-session配置成功后,才可以通过req.session来访问和使用session对象

app.post('/login', function (req, res) {
    req.session.user = req.body // 将请求体中的用户信息存储到session中,user是自定义属性
    req.session.islogin = true // 将用户登录状态存储到session中,islogin也是自定义属性
});
app.get('/logout', function (req, res) {
    req.session.destroy() //只会清空当前用户的session,
});
JWT可以跨域访问

在这里插入图片描述
JWT由三部分组成 Header.Payload.Signature,JWT会存储在浏览器的localStorage和sessionStorage里。
JWT是放在HTTP的请求头Authorization里。格式:Authorization: Bearer <token>

# 安装JWT第三方包
# jsonwebtoken 用于生成JWT字符串,express-jwt用于将jwt字符串解析还原为JSON对象
npm install jsonwebtoken express-jwt
// jsonwebtoken 用于生成JWT字符串
const jwt = require('jsonwebtoken')
// express-jwt用于将jwt字符串解析还原为JSON对象
const expressJWT = require('express-jwt')
// 定义secret密钥,用于加密和解密
const secretKey = 'work_125@!'
// 生成jwt字符串,3个参数分别是,用户信息,加密密钥,配对对象(expiresIn是过期时间,s:秒 h:小时)
const token = jwt.sign({username: 'aaa'},secretKey,{expiresIn:'30s'})
// 要注册中间件,expressJWT是解析Token的中间件,.unless用来指定哪些接口不需要访问权限。
app.use(expressJWT({secret: secretKey }).unless({path: [/^\/api\//]})
app.get('/index', method1 , function (req, res) { 
  // 正常情况下req中没有user属性
  // 当express-jwt中间件配置成功后,可以将JWT字符串中解析出的用户信息挂载到req.user属性上
  const use = req.user
});
// 当解析token字符串过期或不合法时,捕获错误并进行处理。
app.use((err, req, res, next) { 
	if(err.name === 'UnauthorizedError'){
		return res.send({status : 401})
	}
	res.send({status: 500})
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值