日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Node.js项目

發布時間:2024/1/18 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Node.js项目 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.1 創建項目

  • 新建api_server文件夾作為項目根目錄,并在項目根目錄中運行如下的命令,初始化包管理配置文件:
  • npm init -y
  • 運行如下命令,安裝特定版本的express
  • npm i express@4.17.1
  • 在項目根目錄中新建app.js作為整個項目的入口文件,并初始化如下的代碼:
  • // 導入express const express = require('express') // 創建服務器實例對象 const app = express()// 啟動服務器 app.listen(3007, () => {console.log('api server running at http://127.0.0.1:3007'); })

    1.2 配置cors跨域

  • 運行如下命令,安裝cors中間件:
  • npm i cors@2.8.5
  • 在app.js中導入并配置cors中間件:
  • // 導入cors中間件 const cors = require('cors') // 將cors注冊成為全局中間件 app.use(cors())

    1.3 配置解析表單數據的中間件

  • 配置解析application/x-www-form-urlencoded格式的表單數據中間件:
  • app.use(express.urlencoded({ extends: false }))

    1.4 初始化路由相關的文件夾

  • 在項目根目錄中,新建router文件夾,用來存放所有的路由關系。
  • 在項目根目錄中,新建router_handler文件夾,用來存放所有的路由處理函數模塊。
  • 1.5 初始化用戶路由模塊

  • 在router文件夾,新建uer.js文件,作為用戶的路由模塊,并初始化代碼如下:
  • const express = require('express') // 創建路由對象 const router = express.Router()// 注冊新用戶 router.post('/riguser', (req, res) => {res.send('注冊成功!') })// 登陸 router.post('/login', (req, res) => {res.send('登錄成功') })// 將路由對象共享出去 module.exports = router
  • 在app.js中,導入并使用用戶路由模塊:
  • // 導入并注冊用戶路由模塊 const userRouter = require('./router/user') app.use('/api', userRouter)

    1.6抽離用戶路由模塊中的處理函數

    為了保證路由模塊的純粹性,所有的路由處理函數,必須抽離到對應的路由處理函數模塊中。

  • 在/router_handler/user.js中,使用exports對象,分別向外共享如下兩個路由處理函數:
  • // 注冊新用戶的處理函數 exports.regUser = (req, res) => {res.send('注冊成功!') }// 登陸的處理函數 exports.login = (req, res) => {res.send('登錄成功') }
  • 將/router/user.js中的代碼修改為如下結構:
  • // 導入路由處理函數對應的模塊 const user_handler = require('../router_handler/user')// 注冊新用戶 router.post('/riguser', user_handler.regUser)// 登陸 router.post('/login', user_handler.login)

    登陸注冊

    2.1 新建ev_users表

    在my_db_01數據庫中,新建ev_users表:

    2.2 安裝并配置mysql模塊

    在api接口項目中,需要安裝并配置mysql這個第三方模塊,來連接和操作mysql數據庫:

  • 運行如下命令,安裝mysql模塊:
  • npm i mysql@2.18.1
  • 在項目根目錄中新建/db/index.js文件,在此自定義模塊中創建數據庫的連接對象:
  • // 導入mysql模塊 const mysql = require('mysql')// 創建數據庫對象 const db = mysql.createPool({host: '127.0.0.1',user: 'root',password: '88888888',database: 'my_db_01', })module.exports = db

    2.3 注冊

    2.3.0 實現步驟
  • 檢測表單數據是否合法
  • 檢測用戶名是否被占用
  • 對密碼進行加密處理
  • 插入新用戶
  • 2.3.1 檢測表單數據是否合法

    判斷用戶名和密碼是否為空:

    // 注冊新用戶的處理函數 exports.regUser = (req, res) => {// 獲取客戶端提交到服務器的用戶信息const userinfo = req.body// 對表單中的數據進行合法校驗if(!userinfo.username || !userinfo.password){return res.send({stutas: 1,msg: '用戶名或密碼不能為空!'})}console.log(userinfo);res.send('注冊成功!') }
    檢測用戶名是否被占用
  • 導入數據庫操作模塊:
  • const db = require('../db/index')
  • 定義SQL語句
  • 執行SQL語句并更具結果判斷用戶名是否被占用:
  • // 導入數據庫操作模塊 const db = require('../db/index')// 注冊新用戶的處理函數 exports.regUser = (req, res) => {// 獲取客戶端提交到服務器的用戶信息const userinfo = req.body// 對表單中的數據進行合法校驗if(!userinfo.username || !userinfo.password){return res.send({status: 1,msg: '用戶名或密碼不能為空!'})}// 定義sql語句,查詢用戶名是否被占用const sqlStr = 'select * from ev_users where username=?'db.query(sqlStr, [userinfo.username], function(err, results){// 執行SQL語句失敗if(err){console.log(err.message);return res.send({status: 1,msg: err.message,})}// 判斷用戶名是否被占用if(results.length > 0){ return res.send({status: 1,msg: '用戶名已存在!!'})}// 用戶名可用,進行后續流程...}) }
    2.3.3 對密碼進行加密處理
    • 加密之后,無法被逆向破解
    • 同一明文密碼多次加密,得到的加密結果各不相同,保證了安全性。
  • 運行如下命令,安裝指定版本的bcryptjs:
  • npm i bcryptjs@2.4.3
  • 在/router_handler/user.js中,導入bcryptjs:
  • // 導入bcryptjs: const bcrypt = require('bcryptjs')
  • 在注冊用戶的處理函數中,確認用戶名可用之后,調用bcrypt.hashSync(明文密碼,隨機鹽的長度)方法,歲用戶的密碼進行加密:
  • // 對用戶密碼進行加密userinfo.password = bcrypt.hashSync(userinfo.password)
    2.3.4 添加用戶
  • 定義插入用戶的SQL語句:
  • // 定義插入用戶的SQL語句const sql = 'insert into ev_users set ?'
  • 調用db.query()執行SQL語句,插入新用戶:
  • // 調用db.query()插入新用戶db.query(sql, { username: userinfo.username, password: userinfo.password }, (err, results) => {// 執行SQL語句if(err){return res.send({status: 1,msg: err.message,})}if(results.affectedRows !== 1){return res.send({status: 1,msg: '注冊失敗,請稍后再試!'})}// console.log(userinfo);return res.send('注冊成功!')})

    2.4 優化res.send()代碼

  • 在app.js中,所有路由之前,聲明一個全局中間件,為res對象掛載一個res.cc()函數:
  • // 響應數據的中間件 app.use(function(req, res, next){// status = 0 為成功,status = 1 為失敗;默認將 status 的值設置為 1,方便處理失敗的情況res.cc = function(err, status = 1) {res.send({// 狀態status,// 狀態描述,判斷err是錯誤對象,還是字符串msg: err instanceof Error ? err.message : err,})}next() })

    ??一定要在路由之前,封裝res.cc函數

  • 在處理函數里調用res.cc()函數
  • if(err){// console.log(err.message);// return res.send({// status: 1,// msg: err.message,// })return res.cc(err)}

    2.5 優化表單數據驗證

    在實際開發中,前后端都需要對表單的數據進行合法性的驗證,而且,后端作為數據合法性驗證的最后一個關口,在攔截非法數據方面,起到了至關重要的作用。
    單純的使用if…else…的形式對數據合法性進行驗證,效率低下,出錯率高,維護性差。因此,推薦使用第三方數據驗證模塊,來降低出錯率,提高驗證的效率和可維護性,讓后端程序員把更多的精力放在核心業務邏輯的處理上。

  • 安裝@hapi/joi 包,為表單中攜帶的每個數據項,定位驗證規則:
  • npm i @hapi/joi@17.1.0
  • 安裝@escook/express-joi中間件,來實現自動對表單數據進行驗證的功能:
  • npm i @escook/express-joi
  • 新建/schema/user.js用戶信息驗證規則模塊,并初始化代碼如下:
  • const joi = require('@hapi/joi') /*** string()值必須是字符串* alphanum()值只能是包含a-z A-Z 0-9的字符串* min(length)最小長度* max(length)最大長度* required()值是必填項,不能為undefind* pattern(正則表達式)值必須符合正則表達式的規則*/// 用戶名的驗證規則 const username = joi.string().alphanum().min(1).max(10).required() // 密碼的驗證規則 const password = joi.string().pattern(/^[\S]{6, 12}$/).required()// 注冊和登錄表單的驗證規則對象 exports.reg_login_schema = {// 表示需要對req.body中的數據進行驗證body: {username,password,} }
  • 修改.router/user.js中的代碼如下:
  • const express = require('express') // 創建路由對象 const router = express.Router()// 導入路由處理函數對應的模塊 const user_handler = require('../router_handler/user')// 導入驗證表單數據的中間件 const expressJoi = require('@escook/express-joi') // 導入需要的驗證規則對象 const { reg_login_schema } = require('../schema/user')// 注冊新用戶 // 在注冊新用戶的路由中,聲明局部中間件,對當前請求中攜帶的逐句進行驗證 // 數據驗證通過后,會把這次請求流轉給后面的路由處理函數 // 數據驗證失敗后,終止后續代碼的執行,并拋出一個全局的Error錯誤,進入全局錯誤級別中間件中進行處理 router.post('/riguser', expressJoi(reg_login_schema), user_handler.regUser)// 登陸 router.post('/login', user_handler.login)// 將路由對象共享出去 module.exports = router

    登陸

    2.6.0 實現步驟
  • 檢測表單數據是否合法
  • 根據用戶名查詢用戶的數據
  • 判斷用戶輸入的密碼是否正確
  • 生成JWT的Token字符串
  • 2.6.1 檢測登錄表單的數據是否合法
  • 將/router/user.js中登陸的路由代碼修改如下:
  • // 登陸 router.post('/login', expressJoi(reg_login_schema), user_handler.login)

    根據用戶名查詢用戶的數據

  • 接收表單數據
  • const userinfo = req.body
  • 定義SQL語句
  • const sql = 'select * from ev_users where username=?'
  • 查詢數據
  • db.query(sql, userinfo.username, (err, results) => {if(err){return res.cc(err)}if(results.length !== 1){return res.cc('登錄失敗!')}// todo...})

    2.3.6 判斷用戶輸入的密碼是否正確

    核心實現思路:調用bcrypt.compareSync(用戶提交的密碼,數據庫中的密碼)方法比較密碼是否一致。
    返回值是布爾值。

    // 拿著用戶輸入的密碼,和數據庫中存儲的密碼進行對比const compareResult = bcrypt.compareSync(userinfo.password, results[0].password)// 如果對比的結果為false,則證明用戶輸入的密碼錯誤if(!compareResult){return res.cc('登陸失敗!')}// todo:登陸成功,生成Token字符串

    2.6.4 生成JWT的Token字符串

    注意:生成Token字符串時,一定要剔除密碼和頭像的值。

  • 通過ES6的高級語法,快速剔除密碼和頭像的值:
  • // 剔除密碼和頭像的值const user = { ...results[0], password: '',user_pic: '' }
  • 運行以下命令,安裝生成Token字符串的包:
  • npm i jsonwebtoken@8.5.1
  • 在/router_handlwe/user.js模塊的頭部區域,導入jsonwebtoken包
  • // 用這個包生成Token字符串 const jwt = require('jsonwebtoken')
  • 創建config.js文件,并向外共享加密和還原Token的jwtSecretKey字符串
  • module.exports = {jwtSecrecKey: 'lingyuancong' }
  • 將用戶信息對象加密成Token字符串
  • // 導入配置文件 const config = require('../config')// 生成Token字符串 const tokenStr = jwt.sign(user, config.jwtSecrecKey, {expiresIn: '10h', // Token有效期為十小時 })
  • 將生成的Token字符串響應給客戶端:
  • // 生成Token字符串const tokenStr = jwt.sign(user, config.jwtSecretKey, {expiresIn: config.expiresIn, // Token有效期為十小時})res.send({status: 0,msg: '登陸成功!',token: 'Bearer ' + tokenStr,})

    配置解析Token的中間件

  • 運行如下的命令,安裝解析Token的中間件:
  • npm i express-jwt@5.3.3
  • 在app.js中注冊路由之前,配置解析Token的中間件:
  • // 導入配置文件 const config = require('./config')// 解析token的中間件 const expressJWT = require('express-jwt')// 使用.unless({ path: [/^\/api\//] })指定哪些接口不需要進行Token的身份認證
  • 在app.js中的錯誤級別中間件里面,捕獲并處理Token認證失敗后的錯誤:
  • // 定義錯誤級別的中間件 app.use((err, req, res, next) => {// 驗證失敗導致的錯誤if(err instanceof Joi.ValidationError) return res.cc(err)// 身份認證失敗后的錯誤if(err.name === 'UnauthorizeError') return res.cc('身份認證失敗!')// 未知的錯誤res.cc(err) })

    個人中心

    3.1 獲取用戶的基本信息
    3.1.0 實現步驟
  • 初始化路由模塊
  • 初始化路由處理函數模塊
  • 獲取用戶的基本信息
  • 3.1.1 初始化路由模塊
  • 創建/router/userinfo.js路由模塊,并初始化如下的代碼結構
  • // 導入express const express = require('express') // 創建路由模塊 const router = express.Router()// 獲取用戶的基本信息 router.get('/userinfo', (req, res) => {res.send('ok') })// 向外共享路由模塊 module.exports = router
  • 在app.js中導入并使用個人中心的路由模塊:
  • // 導入并注冊用戶信息路由模塊 const userinfoRouter = require('./router/userinfo') // 注意:以 /my 開頭的接口,都是有權限的接口,需要進行Token身份認證 app.use('/my', userinfoRouter)
    3.1.2 初始化路由處理函數模塊
  • 創建/router_handler/userinfo.js路由處理模塊,并初始化如下的代碼結構:
  • // 獲取用戶基本信息的處理函數 exports.getUserInfo = (req, res) => {res.send('ok') }
  • 修改/router/userinfo.js中的代碼
  • // 導入express const express = require('express') // 創建路由模塊 const router = express.Router()// 導入用戶信息的處理模塊 const userinfo_handler = require('../router_handler/userinfo')// 獲取用戶的基本信息 router.get('/userinfo', userinfo_handler.getUserInfo)// 向外共享路由模塊 module.exports = router
    3.1.3 處理用戶的基本信息
  • 在/router_handler/userinfo.js 頭部導入數據庫操作模塊:
  • // 導入數據庫模塊 const db = require('../db/index')
  • 定義SQL語句:
  • // 根據用戶的ID,查詢用戶的基本信息 // 注意:為了防止用戶的密碼泄漏,需要排除password字段 const sql = 'select id, username, nickname, email, uaer_pic from ev_users where id=?'
  • 調用db.query()執行SQL語句:
  • // 導入數據庫模塊 const { result } = require('@hapi/joi/lib/base') const db = require('../db/index')// 獲取用戶基本信息的處理函數 exports.getUserInfo = (req, res) => {// console.log(req);// 定義SQL語句: // 根據用戶的ID,查詢用戶的基本信息 // 注意:為了防止用戶的密碼泄漏,需要排除password字段 const sql = `select id, username, nickname, email, user_pic from ev_users where id=?`// 注意:req對象上的user屬性,是Token解析成功,express-jwt中間件幫我們掛載上去的 db.query(sql, req.body.id, (err, results) => {// 執行SQL語句失敗if(err) return res.cc(err)// 執行SQL語句成功,但是查詢到的數據不唯一if(results.length !== 1) return res.cc('獲取用戶信息失敗!')// 將用戶信息響應給客戶端res.send({status: 0,msg: '獲取用戶基本信息成功!',data: result[0],}) }) }
    3.1.4 更新用戶信息的模塊
  • 在/router/userinfo.js添加更新模塊路由:
  • // 更新用戶基本信息的路由 router.get('/updateUserinfo', userinfo_handler.updateUserInfo)
  • 在/router_handler/userinfo.js添加用戶處理函數模塊:
  • // 更新用戶信息的處理函數 exports.updateUserInfo = (req, res) => {res.send('ok') }
    3.2.2 驗證表單數據
  • 在/schema/user.js驗證規則模塊,定義id,nickname, email的驗證規則如下:
  • // 定義id,nickname,email的驗證規則如下: const id = joi.number().integer().min(1).required() const nickname = joi.string().required() const email = joi.string().email().required()
  • 將數據驗證規則暴露出去:
  • // 驗證規則對象,更新用戶基本信息 exports.update_userinfo_schema = {body:{id,nickname,email: user_email} }
  • 在/router/userinfo.js模塊中,導入驗證數據合法性中間件:
  • // 導入數據合法性的中間件 const expressJoi = require('@escook/express-joi')
  • 在/router/userinfo.js模塊中,導入需要的驗證規則對象:
  • // 導入需要驗證規則模塊 const { update_userinfo_schema } = require('../schema/user')
  • 在/router/userinfo.js模塊中,修改更新用戶信息的路由如下:
  • // 更新用戶基本信息的路由 router.get('/updateUserinfo', expressJoi(update_userinfo_schema), userinfo_handler.updateUserInfo)
    3.2.3 實現更新數據基本信息的功能
  • 定義待執行的SQL語句:
  • const sql = 'update ev_users set ? where id=?'
  • 調用db.query()執行SQL語句并傳參:
  • // 調用db.query()執行SQL語句并傳參db.query(sql, [req.body,req.body.id], (err, results) => {if(err) return res.cc(err)if(results.affectedRows !== 1) return res.cc('修改基本信息失敗!')return res.cc('修改用戶信息成功!')})
    3.3 重置密碼
    3.3.0 實現步驟
  • 定義路由和處理函數
  • 驗證表單數據
  • 實現重置密碼的功能
  • 3.3.1 定義路由和處理函數
  • 新建重置密碼的路由:
  • // 重置密碼的路由 router.post('/updatepwd', userinfo_handler.updatePassword)
  • 定義重置密碼的路由處理函數:
  • // 重置密碼的路由處理函數 exports.updatePassword = (req, res) => {res.send('ok') }
    3.3.2 驗證表單數據
  • 在/schema/user.js模塊中,向外共享驗證規則對象:
  • // 驗證規則密碼 - 重置對象 exports.update_password_schema = {body: {oldPwd: password,newPwd: joi.not(joi.ref('oldPwd')).concat(password),} }
  • 在/router/userinfo.js模塊中,導入要引入的對象:
  • // 重置密碼的路由 router.post('/updatepwd', expressJoi(update_password_schema), userinfo_handler.updatePassword)
    3.3.3 實現重置密碼的功能
  • 根據id查詢用戶是否存在:
  • // 重置密碼的路由處理函數 exports.updatePassword = (req, res) => {const sql = 'select * from ev_users where id=?'db.query(sql, req.user.id, (err, results) => {if(err) return res.cc(err)if(results.length !== 1) return res.cc('用戶不存在!')// TODO:判斷提交的密碼的正確性}) }
  • 判斷提交的就密碼是否正確:
  • // 拿著用戶輸入的密碼,和數據庫中存儲的密碼進行對比const compareResult = bcrypt.compareSync(userinfo.password, results[0].password)// 如果對比的結果為false,則證明用戶輸入的密碼錯誤if(!compareResult){return res.cc('原密碼錯誤!')}
  • 對新密碼進行加密,更新到數據庫:
  • // 定義更新密碼的SQL語句const sql = `update ev_users set password=? where id=?`// 對新密碼進行bcrypt加密const newPwd = bcrypt.hashSync(req.body.newPwd, 10)// console.log(req.user.id);db.query(sql, [newPwd,req.auth.id], (err, results) => {if(err) return res.cc(err)if(results.affectedRows !== 1) return res.cc('更新密碼失敗!')// 更新密碼成功res.cc('更新密碼成功!')})
    3.4 更新用戶頭像
    3.4.0 實現步驟
  • 定義用戶和處理函數
  • 驗證表單數據
  • 實現更新用戶頭像的功能
  • 3.4.1 定義路由和處理函數
  • 新增路由處理的路由
  • // 更新用戶頭像的路由 router.post('/update/avatar', userinfo_handler.updateAvatar)
  • 定義更新頭像的處理函數
  • // 更新用戶頭像的處理函數 exports.updateAvatar = (req, res) => {// 更新用戶頭像的處理函數res.send('ok') }
    3.4.2 驗證表單數據
  • 在schema/user.js驗證規則模塊中,定義avatar的驗證規則如下:
  • // 定義avatar是我驗證規則 const avatar = joi.string().dataUri().required()
  • 向外共享如下的驗證規則對象:
  • // 驗證規則 - 更新頭像 exports.update_avatar_schema = {body: {avatar,} }
  • 修改更新用戶頭像的路由:
  • // 更新用戶頭像的路由 router.post('/update/avatar', expressJoi(update_avatar_schema), userinfo_handler.updateAvatar)
    3.4.3 實現更新用戶頭像的功能
    // 更新用戶頭像的處理函數 exports.updateAvatar = (req, res) => {console.log(req.body);// 更新用戶頭像的處理函數const sql = 'update ev_users set user_pic=? where id=?'db.query(sql, [req.body.avatar, req.auth.id], (err, results) => {if(err) return res.cc(err)if(results.affectedRows !== 1) return res.cc('更新頭像失敗!')return res.cc('更新頭像成功!')}) }

    總結

    以上是生活随笔為你收集整理的Node.js项目的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。