大家好,我是梅巴哥er
,本篇介绍的是在注册/ 登录 / 用户信息更新 中关于cookie携带userid数据的获取和处理。具体是哪些知识点呢?
- 怎么把userid加入到cookie中进行携带
- 怎么获取cookie中的userid数据
- 当用户登录失效时,怎么删除浏览器cookie中的userid信息,并提示用户重新登录
- 当用户更新个人信息时,怎么响应新的数据(一部分老数据要和新修改的数据进行合并)
- 对于这篇博客在express保存请求数据时,Cannot read property ‘_id‘ of undefined
https://blog.csdn.net/tuzi007a/article/details/108401966
中存在的问题进行修复和解释。
对应的知识点:
1,在cookie中携带userid数据
res.cookie('userid', user._id, { maxAge: 1000*60*60*24 })
2,POST请求下,获取cookie中的userid数据
const userid = req.cookies.userid
3,删除浏览器cookie中的userid信息
res.clearCookie('userid')
4,响应新的数据(一部分老数据要和新修改的数据进行合并)
// 先获取到用户新提交的信息
const user = req.body
// 再把需要合并的信息,从老数据中拿出来
const { _id, username, type } = oldUser
// 数据合并
const data = Object.assign({ _id, username, type }, user)
// 把合并后的数据响应出来
res.send({ code: 0, data })
5,从后台获取随机生成的id,并用Object()进行数据类型转换的问题(对那篇博客的内容进行修复和解释)
- 首先,这种方法确实解决了当初获取不到userid的问题
- 其次,这种方法有个弊端
- 就是,在后续要获取这个userid时,获取到的userid和cookie中携带的登录userid,是不一样的
- 这就产生一个新的问题,
- 就是当用户更新信息时,因为登录时的userid和更新信息时获取的userid不一致,导致后台判断用户未登录的错误信息
- 于是,新的解决办法,就是不再引入
const ObjectId = require('mongodb').ObjectId
,也不再做类型转换const id = ObjectId(req.body.id)
,cookie里也不再用后台随机生成的id做userid,res.cookie('userid', id, { maxAge: 1000*60*60*24 })
- 而是把引入和转换都注释掉,在cookie里把
id
换成user._id
。 这样才能获取到一致的userid数据。 - 从而完成用户信息更新。
关于 登录/ 注册 / 更新信息 的代码,全部在这里了,请参考:
var express = require('express');
var router = express.Router();
// UserModel在models.js文件里已经暴露出来了,要拿到这里用,所以要先引入
const UserModel = require('../db/models').UserModel
// console.log(UserModel)
// 引入密码加密的包
const md5 = require('blueimp-md5')
// 如果没有这里的引入,还有后面id的定义,会报错:
// TypeError: Cannot read property '_id' of undefined
// 解决办法就是,先引入,再定义id,最后把user._id换成id即可。
// const ObjectId = require('mongodb').ObjectId
const filter = { password: 0 } // 指定过滤属性
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
// 测试: 定义一个路由,实现用户注册
/*
a) path为 /register
b) 请求方式为post
c) 接收username和password参数
d) admin是已注册用户
e) 注册成功,返回: { code:0, data: { _id: 'abc', username: 'xxx', password: '123' } }
f) 注册失败,返回: {code: 1, msg: '此用户已存在'}
*/
// router.post('/register', (req, res) => {
// /* 1,获取请求参数
// 2,处理
// 3,返回响应数据 */
// const {username, password} = req.body
// if (username === 'admin') {
// res.send({code: 1, msg: '此用户已存在'})
// } else {
// res.send({ code: 0, data: { id: 'abc', username, password } })
// }
// })
// 注册的路由
router.post('/register', function(req, res) {
// 读取请求参数数据
// 此时的id才是后台传过来的id,才能与数据库对照
// const id = ObjectId(req.body.id)
const { username, password, type } = req.body
// console.log(id)
// const _id = id
// console.log(typeof(_id))
// console.log(req.body)
// console.log(req.body.username)
// console.log({ username })
// console.log(username)
// console.log({ username, password, type })
// 处理
// 1,判断 看用户是否存在
UserModel.findOne( { username }, function(err, user) {
// console.log(user)
// console.log(username)
// console.log(user.username)
if (user) { // user已存在,user值为true
// 返回提示错误信息
res.send({ code: 1, msg: '此用户已存在' })
// console.log(user)
} else { // user不存在
// console.log(user)
// 保存注册的用户数据
new UserModel({ username, password: md5(password), type }).save(function(err, user) {
// console.log(user._id)
// 在发送响应数据之前,生成一个cookie(userid: user._id),
// 并交给浏览器保存
// 参数maxAge单位是毫秒,表示cookie存活的时间。
// 1000*60*60*24 是一天
res.cookie('userid', user._id, { maxAge: 1000*60*60*24 })
// 响应数据中,不要携带密码
const data = { _id: user._id, username, type }
res.send({ code: 0, data })
// console.log(err, user)
// res.send(user)
})
}
})
// 返回响应数据
})
// const userModel = new UserModel({
// username: 'ming',
// password: 233,
// type: 'dashen'
// })
// userModel.save((err, user) => {
// console.log(err, 'user is', user)
// })
// 登录的路由
router.post('/login', (req, res) => {
// 获取数据
const { username, password } = req.body
// const id = ObjectId(req.body.id)
// 处理数据
// 根据username和password去查询数据库users,但是这个password是加密的
// 如果有,返回登录成功信息。
// 如果没有,就返回提示登录失败的信息
// filter是个过滤器
UserModel.findOne({ username, password: md5(password) }, filter, (err, user) => {
// console.log(user)
if (user) { // 登录成功
// 生成一个cookie,并交给浏览器保存
res.cookie('userid', user._id, { maxAge: 1000*60*60*24 })
// 返回登录信息,包含user
res.send({ code: 0, data: user})
} else { // 登录失败
res.send({ code: 1, msg: '用户名或密码不正确!'})
}
})
})
// 更新用户信息的路由
router.post('/update', function(req, res) {
// console.log('cookies: ', req.cookies)
// 获取cookie携带的userid
const userid = req.cookies.userid
// console.log('userid: ', userid)
// 获取提交的用户数据
// 对用户userid进行判断, 如果不存在,就说明用户还没登录
if (!userid) {
res.send({code: 1, msg: '请先登录'})
} else {
// 用户已登录,根据userid更新对应的user信息
const user = req.body
// console.log('user: ', user) // 这里面是没有_id的
// user 里面是用户提交的header头像等信息
UserModel.findByIdAndUpdate({ _id: userid }, user, function(err, oldUser) {
// console.log('oldUser', oldUser)
// oldUser里面有_id, username, password, type等信息
// 如果登录失效,则oldUser就不存在了。
// 这时候需要提醒浏览器删除cookie携带的userid
// 所以 这里需要对oldUser做个判断
if (!oldUser) { // 不存在
res.clearCookie('userid')
res.send({code: 1, msg: '请先登录'})
} else { // 存在
const { _id, username, type } = oldUser
// 做用户信息合并,把user里的header头像等新数据,和登录数据进行合并
const data = Object.assign({ _id, username, type }, user)
res.send({ code: 0, data })
}
})
}
})
module.exports = router;