iis服务器助手广告广告
返回顶部
首页 > 资讯 > 数据库 >基于NodeJs+Express+MySQL 实现实现登录注册接口+token生成与解析验证+跨域-CORS
  • 584
分享到

基于NodeJs+Express+MySQL 实现实现登录注册接口+token生成与解析验证+跨域-CORS

expressnode.js 2023-09-03 16:09:05 584人浏览 泡泡鱼
摘要

目录 一、express是什么? 二、安装 express 三、安装Mysql 四、安装 nodemon 实现项目热更新 五、这里先了解下express的post get delete接口 post接口说明: get接口说明 :  DEL

目录

一、express是什么?

二、安装 express

三、安装Mysql

四、安装 nodemon 实现项目热更新

五、这里先了解下express的post get delete接口

post接口说明:

get接口说明 :

 DELETE 接口

六、注册功能

1、流程分析

校验表单数据是否合法

检测用户名是否占用

密码加密处理

插入新用户

2、完整注册接口

regUser(req, res) 注册函数

七、封装错误处理函数(即:注册功能使用的res.cc)

八、登录功能

1、流程分析

1.判断前端提交的后端的数据是否合法。

2.查询登录的用户是否存在。

3.判断当前用户的密码是否正确。

2、生成token字符

 1.安装jsonwebtoken用于生成token

2.导入jsonwebtoken

 3.全局配置文件(里面有token的密钥)

3.使用jwt.sign对用户的信息进行加密,生成 token 字符串 

4.登录成功后将生成的token返回给客户端

3、登录接口的完整代码

1.login()登录函数代码

九、最后附上users路由模块和登录注册函数.js的完整代码

users.js

login.js登录注册函数

接口文档:

十、解析token中间件

 1.安装解析中间件

2.在App.js 中引入

3.注册全局中间件并解析token

4.注册全局错误中间件 当token失效时 返回信息

十一、CORS跨域中间件

 1. 使用 cors 中间件解决跨域问题

完整代码:(jsonp就不做过多解释了)

1、CORS 响应头部 - Access-Control-Allow-Origin

2、CORS 响应头部 - Access-Control-Allow-Headers

3、CORS 响应头部 - Access-Control-Allow-Methods

4、 CORS请求的分类

5、 简单请求

6、预检请求


一、express是什么?

  1. Express 是一个简洁而灵活的 node.js Web应用框架, 提供了一系列强大特性帮助你创建各种 WEB 应用,和丰富的 Http 工具
  2. 使用 Express 可以快速地搭建一个完整功能的网站。
  3. Express 框架核心特性:
  • 可以设置中间件来响应 HTTP 请求。

  • 定义了路由表用于执行不同的 HTTP 请求动作。

  • 可以通过向模板传递参数来动态渲染 html 页面。

二、安装 express

搭建Express项目有两种方式:

  • 方式一:从零搭建自己的express应用结构
  • 方式二:安装express-generator脚手架 一键生成express项目

在这里我们使用方式二快速构建一个express项目:

        express-generator 是 Express 应用程序生成器工具,我们可以使用它来快速创建应用程序框架。

  1. 在项目文件夹下打开node终端
  2. 安装express-generator 脚手架

    npm install -g express-generator
  3. 创建项目
    express expressFrame (expressFrame 是项目名)

         执行完后项目目录下的结构

 注:bin/www 是启动入口文件,在里面可以设置端口号等

 安装依赖

npm install

启动项目
 

npm start

此时在浏览器打开 http://localhost:3000/

 出现以上页面,那么恭喜你express服务器已创建完成

三、安装Mysql

npm i mysql

新建db 数据库文件夹,文件夹下新建index.js 用来配置数据库信息,index.js内容如下

// 导入 mysql 模块const mysql = require('mysql')// 建立与 MySQL 数据库的连接const db = mysql.createPool({host: '127.0.0.1', // 数据库的IP地址port: 3306, //数据库端口号user: 'web2245321733', // 登录数据库的账号password: 'web2245321733', // 登录数据库的密码database: 'web2245321733' // 指定要操作哪个数据库})// 检测数据库是否连接成功db.query("select 1", (err, results) => {if (err) return console.log(err);console.log(results, '数据库链接成功');});module.exports = db

此时重启项目,终端看到打印出数据库链接成功,

四、安装 nodemon 实现项目热更新

在刚才的添加数据库当中,我们发现每次修改代码都需要重启项目,非常麻烦

安装 nodemon 来监控 node.js 源代码的任何变化和自动重启你的服务器

npm install -g nodemon

在package.JSON中修改启动命令

 然后重启项目,就可以了。

五、这里先了解下express的post get delete接口

post接口说明:

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

get接口说明 :

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

 DELETE 接口

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

参数说明:

  • router.post 用于创建post接口  它有两个参数 参数1:路由匹配规则    参数2:请求的回调函数
  • 回调函数的req参数:客户端请求信息,包括 请求头 请求参数等,req.bodey或req.query获取请求参数
  • 回调函数的res参数:用于提交服务端的响应给客户端
  • 调用 res.send() 方法,向客户端响应处理的结果

六、注册功能

1、流程分析

注册的一般流程 1.校验表单数据是否合法 2.检测用户名是否占用 3.密码加密处理 4.插入新用户

校验表单数据是否合法

// 通过 req.body 获取请求体中包含的 url-encoded 格式的数据const userInfo = req.body//【步骤一】对客户端的数据进行校验if (userInfo.username == '' || userInfo.passWord == '') {return res.send({status: 1,msg: '用户名和密码不能为空'})}

检测用户名是否占用

// 定义sql语句,查询用户名是否被占用let sql = 'select * from ev_users where username=?'db.query(sql, [userInfo.username], (error, result) => {if (error) {return res.cc(error)}if (result.length > 0) {return res.cc('用户名已被占用!')}})

密码加密处理

安装bcryptjs 加密包 用于密码加密

npm i bcryptjs

 引入加密包

// 导入 bcryptjs 加密包const bcrypt = require('bcryptjs')

调用 bcrypt.hashSync() 对密码加密

// 调用 bcrypt.hashSync() 对密码加密userInfo.password = bcrypt.hashSync(userInfo.password, 10)

 说明:bcrypt.hashSync() 的参数1:要加密的密码  参数2: 加密等级 填10即可

插入新用户

前面我们已经连接过数据库了,这里我们直接引入数据库操作模块

// 导入数据库操作模块const db = require('../../db/index')

 定义插入新用户的 sql 语句

// 定义插入新用户的 SQL 语句let sql1 = 'insert into ev_users set ?'

 调用 db.query() 执行 sql 语句 插入新用户 并给客户端返回结果

// 调用 db.query() 执行 sql 语句db.query(sql1, {username: userInfo.username,password: userInfo.password}, (error, result) => {if (error) return res.cc(error)// 判断影响行数是否为 1if (result.affectedRows !== 1) return res.cc('注册用户失败!')return res.cc('注册用户成功', 0, {username: userInfo.username})})

2、完整注册接口

  • 打开routes文件夹下的users.js 路由模块,添加以下内容
router.post('/add', (req, res, next) => {// 通过 req.body 获取请求体中包含的 url-encoded 格式的数据console.log(req.body)const userInfo = req.body//【步骤一】对客户端的数据进行校验if (userInfo.username == '' || userInfo.password == '') {return res.send({status: 1,msg: '用户名和密码不能为空'})}// 【步骤二】执行定义好的注册函数regUser(req, res)});

regUser(req, res) 注册函数

在这里我单独新建了个login.js文件用于写注册和登录的处理的函数放

 引入

// 导入写好的注册/登录函数const {regUser,login} = require('../public/javascripts/login')

regUser(req, res) 注册函数内容如下:

// 导入数据库操作模块const db = require('../../db/index')// 导入 bcryptjs 加密包const bcrypt = require('bcryptjs')exports.regUser = (req, res) => {// 获取客户端提交到服务器的用户信息const userInfo = req.body// 定义sql语句,查询用户名是否被占用let sql = 'select * from ev_users where username=?'db.query(sql, [userInfo.username], (error, result) => {if (error) {return res.cc(error)}if (result.length > 0) {return res.cc('用户名已被占用!')}// 调用 bcrypt.hashSync() 对密码加密userInfo.password = bcrypt.hashSync(userInfo.password, 10)// 定义插入新用户的 SQL 语句let sql1 = 'insert into ev_users set ?'// 调用 db.query() 执行 sql 语句db.query(sql1, {username: userInfo.username,password: userInfo.password}, (error, result) => {if (error) return res.cc(error)// 判断影响行数是否为 1if (result.affectedRows !== 1) return res.cc('注册用户失败!')return res.cc('注册用户成功', 0, {username: userInfo.username})})})}exports.login = (req, res) => {}

七、封装错误处理函数(即:注册功能使用的res.cc)

在注册功能里我对res.send向客户端响应函数做了处理,

在app.js中,放在路由前面

//封装错误处理函数app.use((req, res, next) => {res.cc = function(err, status = 1, data = {}) {res.send({status,data,message: err instanceof Error ? err.message : err})}next()})

八、登录功能

1、流程分析

登录的一般流程 1.判断前端提交的后端的数据是否合法。 2.查询登录的用户是否存在。 3.判断当前用户的密码是否正确。

1.判断前端提交的后端的数据是否合法。

// 通过 req.body 获取请求体中包含的 url-encoded 格式的数据console.log(req.body)const userInfo = req.body//【步骤一】对客户端的数据进行校验if (userInfo.username == '' || userInfo.password == '') {return res.send({status: 1,msg: '用户名和密码不能为空'})}

2.查询登录的用户是否存在。

// 定义 SQL 语句const sql = 'select * from ev_users where username=?'// 执行 SQL 语句,根据用户名查询用户的信息db.query(sql, userInfo.username, (err, result) => {// 执行 SQL 语句失败if (err) return res.cc(err)// 执行 SQL 语句成功,但是获取的数据条数不为1 也是失败的if (result.length !== 1) return res.cc('登录失败!')// 经过上方俩条判断条件,则证明执行 SQL 成功})

3.判断当前用户的密码是否正确。

使用 加密包的bcrypt.compareSync方法对比用户提交的密码和数据库中的密码是否一致,如果一直即:登录成功

// TODO :判断密码是否正确const comRes = bcrypt.compareSync(userInfo.password, result[0].password)if (!comRes) return res.cc('登陆失败')

2、生成token字符

密码正确的话,登录成功,根据用户信息生成唯一的token返回给客户端

 1.安装jsonwebtoken用于生成token

npm i jsonwebtoken

2.导入jsonwebtoken

// 导入生成Token的包const Jwt = require('jsonwebtoken')

 3.全局配置文件(里面有token的密钥)

config.js放在根目录

// 全局配置文件 config.jsmodule.exports = {// 加密和解密 token 的密钥jwtSecreTKEy: 'itheima No1. ^_^',// token 有效期expiresIn: '10h'}

导入

// 导入全局配置文件(里面有token的密钥)const config = require('../../config')

3.使用jwt.sign对用户的信息进行加密,生成 token 字符串 

jwt.sign 有三个参数依次是 生成token的数据,加密的形式,token有效期

 加密前先处理用户信息,将用户的敏感信息置空(如:密码等)

// 在服务器端生成 Token 字符串const user = {...result[0], // 解构用户信息password: '', //密码等敏感信息置空}// 对用户的信息进行加密,生成 token 字符串 const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: config.expiresIn //tonken 有效期})

4.登录成功后将生成的token返回给客户端

// 调用 res.send 将Token响应给客户端res.send({status: 0,data: {user: user,token: 'Bearer ' + tokenStr,},message: '登录成功!!!',})

3、登录接口的完整代码

router.post('/login', (req, res, next) => {// 通过 req.body 获取请求体中包含的 url-encoded 格式的数据// console.log(req.body)const userInfo = req.body//对客户端的数据进行校验if (userInfo.username == '' || userInfo.password == '') {return res.send({status: 1,msg: '用户名和密码不能为空'})}// 执行定义好的登录函数login(req, res)});

1.login()登录函数代码

exports.login = (req, res) => {console.log('user', req.user);// 接收表单的数据const userInfo = req.body// 定义 SQL 语句const sql = 'select * from ev_users where username=?'// 执行 SQL 语句,根据用户名查询用户的信息db.query(sql, userInfo.username, (err, result) => {// 执行 SQL 语句失败if (err) return res.cc(err)// 执行 SQL 语句成功,但是获取的数据条数不为1 也是失败的if (result.length !== 1) return res.cc('登录失败!')// 经过上方俩条判断条件,则证明执行 SQL 成功// TODO :判断密码是否正确const comRes = bcrypt.compareSync(userInfo.password, result[0].password)if (!comRes) return res.cc('登陆失败')// 在服务器端生成 Token 字符串const user = {...result[0], // 解构用户信息password: '', //密码等敏感信息置空}// 对用户的信息进行加密,生成 token 字符串 const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: config.expiresIn //tonken 有效期})// 调用 res.send 将Token响应给客户端res.send({status: 0,data: {user: user,token: 'Bearer ' + tokenStr,},message: '登录成功!!!',})})}

九、最后附上users路由模块和登录注册函数.js的完整代码

users.js

var express = require('express');var router = express.Router();// 导入写好的注册/登录函数const {regUser,login} = require('../public/javascripts/login')router.get('/', function(req, res, next) {// 获取客户端提交到服务器的用户信息const userInfo = req.bodyif(req.user){return res.cc('获取成功', 0, req.user)}// 获取到中间件的时间res.send('GET 请求成功');});router.post('/add', (req, res, next) => {// 通过 req.body 获取请求体中包含的 url-encoded 格式的数据console.log(req.body)const userInfo = req.body//【步骤一】对客户端的数据进行校验if (userInfo.username == '' || userInfo.password == '') {return res.send({status: 1,msg: '用户名和密码不能为空'})}// 【步骤二】执行定义好的注册函数regUser(req, res)});router.post('/login', (req, res, next) => {// 通过 req.body 获取请求体中包含的 url-encoded 格式的数据// console.log(req.body)const userInfo = req.body//对客户端的数据进行校验if (userInfo.username == '' || userInfo.password == '') {return res.send({status: 1,msg: '用户名和密码不能为空'})}// 执行定义好的登录函数login(req, res)});// // 在这里挂载对应的路由// 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;

login.js登录注册函数

// 导入数据库操作模块const db = require('../../db/index')// 导入 bcryptjs 加密包const bcrypt = require('bcryptjs')// 导入生成Token的包const jwt = require('jsonwebtoken')// 导入全局配置文件(里面有token的密钥)const config = require('../../config')exports.regUser = (req, res) => {// 获取客户端提交到服务器的用户信息const userInfo = req.body// 定义sql语句,查询用户名是否被占用let sql = 'select * from ev_users where username=?'db.query(sql, [userInfo.username], (error, result) => {if (error) {return res.cc(error)}if (result.length > 0) {return res.cc('用户名已被占用!')}// 调用 bcrypt.hashSync() 对密码加密userInfo.password = bcrypt.hashSync(userInfo.password, 10)// 定义插入新用户的 SQL 语句let sql1 = 'insert into ev_users set ?'// 调用 db.query() 执行 sql 语句db.query(sql1, {username: userInfo.username,password: userInfo.password}, (error, result) => {if (error) return res.cc(error)// 判断影响行数是否为 1if (result.affectedRows !== 1) return res.cc('注册用户失败!')return res.cc('注册用户成功', 0, {username: userInfo.username})})})}exports.login = (req, res) => {console.log('user', req.user);// 接收表单的数据const userInfo = req.body// 定义 SQL 语句const sql = 'select * from ev_users where username=?'// 执行 SQL 语句,根据用户名查询用户的信息db.query(sql, userInfo.username, (err, result) => {// 执行 SQL 语句失败if (err) return res.cc(err)// 执行 SQL 语句成功,但是获取的数据条数不为1 也是失败的if (result.length !== 1) return res.cc('登录失败!')// 经过上方俩条判断条件,则证明执行 SQL 成功// TODO :判断密码是否正确const comRes = bcrypt.compareSync(userInfo.password, result[0].password)if (!comRes) return res.cc('登陆失败')// 在服务器端生成 Token 字符串const user = {...result[0], // 解构用户信息password: '', //密码等敏感信息置空}// 对用户的信息进行加密,生成 token 字符串 const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: config.expiresIn //tonken 有效期})// 调用 res.send 将Token响应给客户端res.send({status: 0,data: {user: user,token: 'Bearer ' + tokenStr,},message: '登录成功!!!',})})}

到此我们的登录和注册接口已经实现,

接口文档:

注册:post       http://127.0.0.1/users/add

           请求参数:username:用户名   

                             password:密码

登录:post       http://127.0.0.1/users/login

           请求参数:username:用户名   

                             password:密码

十、解析token中间件

在刚刚我没完成了token的生成,现在我们做一个中间件用来解析token,来对用户进行身份认证

 1.安装解析中间件

npm i express-jwt

2.在App.js 中引入

//token解析中间件 一定要在路由之前配置解析 Token 的中间件const expressJWT = require('express-jwt')//映入解密const config = require('./config')

3.注册全局中间件并解析token

// 注册全局中间件  链式调用 unless 方法,接收一个配置对象,path 字段设置一个正则表达式,表示不需要 token 身份认证的路由前缀。app.use(expressJWT({// 加密时设置的密钥secret: config.jwtSecretKey,// 设置算法alGorithms: ['HS256'],// 无token请求不进行解析,并且抛出异常// credentialsRequired: false}).unless({path: ['/users/add','/users/login',{url: /^\/public\/.*/,methods: ['GET', 'POST']}]// path: ['/users/login','/users']}))

4.注册全局错误中间件 当token失效时 返回信息

// 错误中间件 当token失效时 返回信息app.use((err, req, res, next) => {if (err.name === 'UnauthorizedError') {res.status(401).send({status: 1,data: {},message: '身份认证失败!'});}});

十一、CORS跨域中间件

注册登录接口写好了,但是使用的时候会有一个很严重的问题:不支持跨域请求。

解决接口跨域问题的方案主要有两种:

① CORS(主流的解决方案,推荐使用)

② JSONP(有缺陷的解决方案:只支持 GET 请求)

 1. 使用 cors 中间件解决跨域问题

cors 是 Express 的一个第三方中间件。通过安装和配置 cors 中间件,可以很方便地解决跨域问题。

使用步骤分为如下 3 步:

① 运行 npm install cors 安装中间件

npm install cors

② 使用 const cors = require(‘cors’) 导入中间件

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

③ 在路由之前调用 app.use(cors()) 配置中间件

app.use(cors())

完整代码:(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)})// 一定要在路由之前,配置 cors 这个中间件,从而解决接口跨域的问题const cors = require('cors')app.use(cors())

注意事项:

①CORS 主要在服务器端进行配置。客户端浏览器无须做任何额外的配置,即可请求开启了CORS的接口。

②CORS在浏览器中有兼容。只有支持XMLHttpRequest Level2的浏览器,才能正常访问开启了CORS的服务端接口(例如:IE10+、Chrome4+、FireFox3.5+)。

1、CORS 响应头部 - Access-Control-Allow-Origin

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

res.setHeader('Access-Control-Allow-Origin','*')

2、CORS 响应头部 - 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 三者之一)
如果客户端向服务器发送了额外的请求头信息,则需要在服务器端,通过 Access-Control-Allow-Headers 对额外的请求头进行声明,否则这次请求会失败!

 

// 允许客户端额外向服务器发送 Content-Type 请求头和 X-Custom-Header 请求头// 注意: 多个请求头之间使用英文的逗号进行分割res.setHeader('Access-Control-Allow-Headers ''Content-Type X-Custom-Header')

3、CORS 响应头部 - Access-Control-Allow-Methods

默认情况下,CORS 仅支持客户端发起 GET、POST、HEAD 请求。
如果客户端希望通过 PUT、DELETE 等方式请求服务器的资源,则需要在服务器端,通过 Access-Control-Alow-Methods来指明实际请求所允许使用的 HTTP 方法。示例代码如下:

// 只允许 POST、GET、DELETE、HEAD 请求方法res,setHeader('Access-Control-A1low-Methods','POST,GET,DELETE,HEAD') // 允许所有的 HTTP 请求方法 res,setHeader('Access-Control-A1low-Methods','*')

4、 CORS请求的分类

客户端在请求 CORS 接口时,根据 请求方式和请求头的不同,可以将 CORS 的请求分为两大类,分别是:
① 简单请求
② 预检请求

5、 简单请求

同时满足以下两大条件的请求,就属于简单请求:
① 请求方式:GET、POST、HEAD 三者之一
② HTTP 头部信息不超过以下几种字段:无自定义头部字段、Accept、Accept-Language、Content-Language、DPR、Downlink、Save-Data、Viewport-Width、Width 、Content-Type(只有三个值application/x-www-form-urlencoded、multipart/form-data、text/plain)

6、预检请求

只要符合以下任何一个条件的请求,都需要进行预检请求:
① 请求方式为 GET、POST、HEAD 之外的请求 Method 类型
② 请求头中包含自定义头部字段
③ 向服务器发送了 application/json 格式的数据

在浏览器与服务器正式通信之前,浏览器会先发送 OPTION 请求进行预检,以获知服务器是否允许该实际请求,所以这一次的 OPTION 请求称为“预检请求”。服务器成功响应预检请求后,才会发送真正的请求,并且携带真实数据。

7.、简单请求和预检请求的区别

简单请求的特点:客户端与服务器之间只会发生一次请求。
预检请求的特点:客户端与服务器之间会发生两次请求,OPTION 预检请求成功之后,才会发起真正的请求。

2、最后附上app.js完整代码 

// 导入 expressvar express = require('express');var path = require('path');var cookieParser = require('cookie-parser');var logger = require('morgan');// 引入路由模块var indexRouter = require('./routes/index');var usersRouter = require('./routes/users');// 创建服务器实例var app = express();app.use(logger('dev'));// 处理 application/jsonapp.use(express.json());// 配置解析表单数据的中间件 处理 x-www-form-urlencodedapp.use(express.urlencoded({extended: false}));app.use(cookieParser());app.use(express.static(path.join(__dirname, 'public')));//token解析中间件 一定要在路由之前配置解析 Token 的中间件const expressJWT = require('express-jwt')//映入解密const config = require('./config')// 注册全局中间件  链式调用 unless 方法,接收一个配置对象,path 字段设置一个正则表达式,表示不需要 token 身份认证的路由前缀。app.use(expressJWT({// 加密时设置的密钥secret: config.jwtSecretKey,// 设置算法algorithms: ['HS256'],// 无token请求不进行解析,并且抛出异常// credentialsRequired: false}).unless({path: ['/users/add','/users/login',{url: /^\/public\/.*/,methods: ['GET', 'POST']}]// path: ['/users/login','/users']}))// 【必须在配置 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())//定义第一个全局中间件app.use((req, res, next) => { //res用于返回客户端 req客户端的请求参数  next() 提交给下一个中间件// 只允许  请求方法res.setHeader('Access-Control-Allow-Methods', 'POST, GET, DELETE,HEAD')// 响应头 允许所有的 HTTP 请求方法res.setHeader('Access-Control-Allow-Methods', '*')// 如果指定了 Access-Control-Allow-Origin 字段的值为通配符 *,表示允许来自任何域的请求res.setHeader('Access-Control-Allow-Origin', '*')// res.setHeader("Access-Control-Allow-Headers", "content-type,Authorization");next();})//封装错误处理函数app.use((req, res, next) => {res.cc = function(err, status = 1, data = {}) {res.send({status,data,message: err instanceof Error ? err.message : err})}next()})// 错误中间件 当token失效时 返回信息app.use((err, req, res, next) => {if (err.name === 'UnauthorizedError') {res.status(401).send({status: 1,data: {},message: '身份认证失败!'});}});// 挂载路由app.use('/', indexRouter);app.use('/users', usersRouter);module.exports = app;

 跨域这部分和jsonp参考了以下文章 

【nodejs-03】黑马nodejs学习笔记03-express中间件与跨域_简单长庚的博客-CSDN博客

来源地址:https://blog.csdn.net/weixin_46408500/article/details/130647530

您可能感兴趣的文档:

--结束END--

本文标题: 基于NodeJs+Express+MySQL 实现实现登录注册接口+token生成与解析验证+跨域-CORS

本文链接: https://www.lsjlt.com/news/392499.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作