综合案例:使用Express开发接口服务(续)
Posted So istes immer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了综合案例:使用Express开发接口服务(续)相关的知识,希望对你有一定的参考价值。
⑦用户登录开发
1.获取请求体数据
2.数据验证
3.生成token
4.发送成功响应(包含token的用户信息)
基于JWT的身份验证 https://blog.csdn.net/YINZHE__/article/details/120080256
config/config.default.js中的jwtSecret可以用UUID保证唯一性 http://www.uuid.online/
默认生成的token是永久有效的,但是可以自己设置有效期时间,见controller/user.js
config/config.default.js
/**
* 默认配置
*/
module.exports = {
dbUrl: 'mongodb://localhost:27017/realworld',
jwtSecret: '3301a30b-7355-4398-bc02-331eb32c9f64'
}
util/jwt.js
const jwt = require('jsonwebtoken')
const { promisify } = require('util')
exports.sign = promisify(jwt.sign)
exports.verify = promisify(jwt.verify)
exports.decode = promisify(jwt.decode)
controller/user.js
const { User } = require('../model')
const jwt = require('../util/jwt')
const { jwtSecret } = require('../config/config.default')
// 用户登录
exports.login = async (req, res, next) => {
try {
// 1.数据验证
// 2.生成token
const user = req.user.toJSON()
console.log(user)
const token = await jwt.sign({
userId: user._id
}, jwtSecret,{
expiresIn: 60 * 60 * 24
})
// 3.发送成功响应(包含token的用户信息)
delete user.password
res.status(200).json({
...user,
token
})
} catch(err) {
next(err)
}
}
... //其它代码不变
validator/user.js
const validate = require('../middleware/validate')
const { body } = require('express-validator')
const { User } = require('../model')
const md5 = require('../util/md5')
... //原代码不变
exports.login = [
validate([
body('user.email').notEmpty().withMessage('邮箱不能为空'),
body('user.password').notEmpty().withMessage('密码不能为空')
]),
validate([
body('user.email').custom(async (email, { req }) => {
const user = await User.findOne({ email })
.select(['email','username','bio','image','password'])
if (!user) {
return Promise.reject('用户不存在')
}
// 将数据挂载到请求对象中,后续的中间件也可以使用了
req.user = user
})
]),
validate([
body('user.password').custom(async (password, { req }) => {
if(md5(password) !== req.user.password) {
return Promise.reject('密码错误')
}
})
])
]
router/user.js
const express = require('express')
const userCtrl = require('../controller/user')
const userValidator = require('../validator/user')
const router = express.Router()
// 用户登录
router.post('/users/login', userValidator.login, userCtrl.login)
... //原代码不变
module.exports = router
生成token并发送
⑧获取用户信息
在获取之前,首先要验证token
router/user.js
const express = require('express')
const userCtrl = require('../controller/user')
const userValidator = require('../validator/user')
const auth = require('../middleware/auth')
const router = express.Router()
... //原代码不变
// 获取当前登录用户
router.get('/user', auth, userCtrl.getCurrentUser)
... //原代码不变
module.exports = router
controller/user.js
const { User } = require('../model')
const jwt = require('../util/jwt')
const { jwtSecret } = require('../config/config.default')
... //原代码不变
// 获取当前登录用户
exports.getCurrentUser = async (req, res, next) => {
try {
res.status(200).json({
user: req.user
})
} catch(err) {
next(err)
}
}
... //原代码不变
middleware/auth.js
const { verify } = require('../util/jwt')
const { jwtSecret } = require('../config/config.default')
const { User } = require('../model')
module.exports = async (req,res,next) => {
// 从请求头获取token数据
let token = req.headers['authorization']
token = token ? token.split('Bearer ')[1] : null
if(!token) {
return res.status(401).end()
}
try {
const decodedToken = await verify(token, jwtSecret)
req.user = await User.findById(decodedToken.userId)
next()
} catch(err) {
return res.status(401).end()
}
}
效果
这里的token是之前登录生成的token
在postman中,也可以统一设置请求头中的Authorization,这样就不用每次添加了
以上是关于综合案例:使用Express开发接口服务(续)的主要内容,如果未能解决你的问题,请参考以下文章
Express接口综合案例(创建项目配置常用中间件路由设计提取控制器模块配置错误统一处理中间件用户注册的数据验证,密码加密)