使用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