我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第11篇文章
封装全局中间件,
- 封装的全局中间件,一定要在最前面注册app.use()
例:封装res.send的语句
app.use((req, res, next) => {
res.cc = (err, status = 400) => {
res.send({
message: err instanceof Error ?err.message :err,
status
})
}
next()
})
注意: err instanceof Error判断是否是错误对象(查询sql语句失败的结果),还是错误信息
对用户密码进行加密处理
为了保证密码的安全性,不建议在数据库以 明文 的形式保存用户密码,推荐对密码进行 加密 存储
使用 bcryptjs 对用户密码进行加密
优点:
-
加密之后的密码,无法被逆向破解
-
同一明文密码多次加密,得到的加密结果各不相同,保证了安全性
- 运行如下命令,安装指定版本的 bcryptjs
npm i bcryptjs@2.4.3- 在 /router_handler/user.js 中,导入 bcryptjs , router_handle(路由处理函数的文件夹)
const bcrypt = require('bcryptjs')- 在注册用户的处理函数中,确认用户名可用之后,调用 bcrypt.hashSync(明文密码, 随机密码的 长度) 方法,对用户的密码进行加密处理:
// 对用户的密码,进行 bcrype 加密,返回值是加密之后的密码字符串 userinfo.password = bcrypt.hashSync(userinfo.password, 10)
使用 bcryptjs 对用户密码进行解密
核心实现思路:调用 bcrypt.compareSync(用户提交的密码, 数据库中的密码) 方法比较密码是否一致
返回值是布尔值(true 一致、false 不一致)
// 拿着用户输入的密码,和数据库中存储的密码进行对比
const compareResult = bcrypt.compareSync(userinfo.password, results[0].password)
token
通过jsonwebtoken包(生成JWT字符串), express-jwt包(将字符串还原成JSON对象)
- 创建config文件夹,token.js文件
秘钥:secret 有效期:expiresIn
const secretKey = '字符串'
const expiresIn = '24h
生成token
// 导入token.js
const { secretKey, expiresIn } = require('../config/token.js')
登录后(生成token)
const jwt = require('jsonwebtoken')
// 建议不要把密码添加进去, expiresIn有效期
const tokenStr = jwt.sign({ username: 'zs' }, secretKey, { expiresIn })
// 用户信息对象, 秘钥, 配置对象
解析token
// 导入token.js
const { secretKey } = require('../config/token.js')
const { expressjwt } = require('express-jwt')
// expressjwt({ secret: secretKey, algorithms: ["HS256"] })用来解析token的中间件
// unless({ path: [ /^/api// ] }) 用来指定哪些接口不需要访问权限
app.use(expressjwt({ secret: secretKey, algorithms: ["HS256"] }).unless({ path: [ /^/api// ] }))
req.auth.user // 拿到解析的对象
// 捕获不合法或过期的token
app.use((err, req, res, next) => {
if (err.name === 'UnauthorizedError') return res.status(401).send({ status: 401, message: '无效的token' })
// 其他原因导致的错误
res.send({ status: 500, message: '未知错误' })
})