使用node+express+mongodb實現用戶註冊、登錄和驗證功能
- 2019 年 11 月 7 日
- 筆記
無論是手機端還是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, '用戶不存在') 這個就相當於下面這麼多行程式碼了,簡潔明了
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