使用node+express+mongodb实现用户注册、登录和验证功能
无论是手机端还是pc端,几乎都包含登录注册方面功能,今天就使用node+express+mongodb实现一套登录注册功能,这里需要自己去安装MongoDB环境,如果没有安装可以看这篇关于MongoDB安装的步https://www.cnblogs.com/zhoulifeng/p/9429597.html
实现功能
- 注册 密码加密
- 登录 校验 token处理
1.环境搭建运行
在目录里安装express和mongoose,并在根目录创建server.js文件和models文件,
在server.js文件中
const express = require('express'); const app = express(); app.listen(3001,() =>{ console.log('http://localhost:3001') })
在你models文件中链接MongoDB数据库,express-auth这个就是你数据库的名字,27017是你数据库的端口号,mongodb不需要打开数据库可视化工具,根据名字就自动创建这个数据库名了
const mongoose = require('mongoose') // 链接数据库 mongoose.connect('mongodb://localhost:27017/express-auth',{ useCreateIndex:true, useNewUrlParser:true })
在你server.js写一点路由,测试数据库是否链接成功,启动服务的话,你可以全局安装nodemon ,然后通过在命令控制台出入nodemon server.js就可以,会实时更新我们修改的代码,
app.get('/api/test',async(req,res) =>{ res.send('ok') })
在这里我们可以在Vcode中安装一个REST Client插件,可以不需要postman就可以调试接口,也是在你的根目录创建一个http结尾的目录。url就是我们的访问域名,定义一个全局的,get就是请求方式,后面test就是请求名。在右边就可以看到我们返回的结果。要在server.js目录引入才能生效。
注册功能
首先建立模型,在models.js建立对应的模型,这里因为是登录和注册,就写两个字段就行,如果需要,可以自行添加对应的字段名,unique表示用户名是唯一的,不让重复添加
const UserSchema = new mongoose.Schema({ username:{ type:String, unique:true //字段是否唯一 }, password:{ type:String } }) const User = mongoose.model('User',UserSchema) module.exports = {User}
在你server.js文件,先引入这个模型
const {User} = require('./models')
编写接口,create是mongoose语法,创建
// 注册 app.post('/api/register',async(req,res) =>{ const user = await User.create({ username:req.body.username, password:req.body.password }) // 返回出去 res.send(user) })
然后在test.http文件测试,可以看出来返回的结果是我们填写的用户名和密码,但是这样密码暴露了,对用户信息造成安全隐私问题。应该是用户填写密码,保存数据库的时候,应该是一段乱文,服务端看不懂的一段密码。这里就需要用到对密码加密处理,以前经常用的是md5,现在最常用的是bcryptjs加密方式。
安装加密bcryptjs依赖包,这个和bcrypt原理是一样的,如果第bcrypt安装不成功,就是要bcryptjs安装就行,用法 一样的
cnpm install bcryptjs --save
然后直接对模型进行修改就行,直接在password添加set,对返回值进行处理就行,通过bcryptjs中的hashSync生成hash密码
const UserSchema = new mongoose.Schema({ username:{ type:String, unique:true //字段是否唯一 }, password:{ type:String, set(val){ // 通过bcryptjs对密码加密返回值 第一个值返回值, 第二个密码强度 return require('bcryptjs').hashSync(val,10) } } })
再次测试,因为是post请求,需要添加Content-Type: application/json,所有全局定义一个@json,然后只要是post请求的就直接tongg{{json}}使用
上面这种返回密码格式,就是我们需要的格式,保障用户密码的安全性
登录功能
登录和注册用的字段一样的。所以不需要建立模型编写,登录时候,第一步肯定先判断用户是不是存在,如果用户不存在,直接返回状态码和错误信息,也不需要执行下一步,第二步用户名过了,接来下就是验证密码是否正确,通过compareSync验证面密码是否正确,如果正确就返回,不正确的话也是返回状态码和错误信息,最后一步就是生成token,返回客户端,客户端可以通过token判断是哪个用户。SECRET定义的是一个秘钥,先随便填写,这个秘钥应该不要出现在代码中,
const SECRET = 'ewgfvwergvwsgw5454gsrgvsvsd'
安装 jsonwebtoken依赖包 并引入
const jwt = require('jsonwebtoken')
像下面这些判断用户存在或者密码不正确,没有写好几行代码才能解决,推荐安装一个插件http-assert错误提示
const assert = require('http-assert')
引入之后,就可以使用了(本次案例中没有使用,其他项目中使用了,测试没有任何问题,放心使用)
assert(user, 422, '用户不存在') 这个就相当于下面这么多行代码了,简洁明了
if(!user) {
return res.status(422).send({
message:"用户不存在"
})
}
app.post('/api/login',async(req,res) =>{ const user = await User.findOne({ username:req.body.username }) if(!user) { return res.status(422).send({ message:"用户不存在" }) } const isPasswordValid = require('bcryptjs').compareSync( req.body.password, user.password ) if(!isPasswordValid){ return res.status(422).send({ message:"密码无效" }) } const token = jwt.sign({ id:String(user._id) },SECRET) // 生成token res.send({ user, token }) })
上面就可以实现登录成功之后返回token,这个token里面包含用户的一个id.
token校验
token校验,验证比如获取用户信息,发送什么东西的时候,判断token是否存在,如果存在可以执行,否则不能执行,全局写一个中间件,当每个接口使用的时候,直接调用就可以
const auth = async(req,res) =>{ const raw = String(req.headers.authorization).split(' ').pop(); // 验证 const {id} = jwt.verify(raw,SECRET) req.user = await User.findById(id) }
例如:请求用户列表,需要传token验证是否存在。auth就是验证这个token是否存在。
app.get('/api/profile',auth,async(req,res) =>{ res.send(req.user) })
最终所有的代码已提交到github中,有需要的可以下载看看https://github.com/MrZHLF/node-express-mongodb