生活随笔
收集整理的這篇文章主要介紹了
Node.js项目
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1.1 創建項目
新建api_server文件夾作為項目根目錄,并在項目根目錄中運行如下的命令,初始化包管理配置文件:
npm init -y
運行如下命令,安裝特定版本的express
npm i express@4.17.1
在項目根目錄中新建app.js作為整個項目的入口文件,并初始化如下的代碼:
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中間件:
const cors
= require ( '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文件,在此自定義模塊中創建數據庫的連接對象:
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 : '用戶名或密碼不能為空!' } ) } const sqlStr
= 'select * from ev_users where username=?' db
. query ( sqlStr
, [ userinfo
. username
] , function ( err, results ) { 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:
const bcrypt
= require ( 'bcryptjs' )
在注冊用戶的處理函數中,確認用戶名可用之后,調用bcrypt.hashSync(明文密碼,隨機鹽的長度)方法,歲用戶的密碼進行加密:
userinfo
. password
= bcrypt
. hashSync ( userinfo
. password
)
2.3.4 添加用戶
定義插入用戶的SQL語句:
const sql
= 'insert into ev_users set ?'
調用db.query()執行SQL語句,插入新用戶:
db
. query ( sql
, { username : userinfo
. username
, password : userinfo
. password
} , ( err, results ) => { if ( err
) { return res
. send ( { status : 1 , msg : err
. message
, } ) } if ( results
. affectedRows
!== 1 ) { return res
. send ( { status : 1 , msg : '注冊失敗,請稍后再試!' } ) } return res
. send ( '注冊成功!' ) } )
2.4 優化res.send()代碼
在app.js中,所有路由之前,聲明一個全局中間件,為res對象掛載一個res.cc()函數:
app
. use ( function ( req, res, next ) { res
. cc = function ( err, status = 1 ) { res
. send ( { status
, msg : err
instanceof Error ? err
. message
: err
, } ) } next ( )
} )
??一定要在路由之前,封裝res.cc函數
在處理函數里調用res.cc()函數
if ( err
) { 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' )
const username
= joi
. string ( ) . alphanum ( ) . min ( 1 ) . max ( 10 ) . required ( )
const password
= joi
. string ( ) . pattern ( / ^[\S]{6, 12}$ / ) . required ( )
exports
. reg_login_schema
= { 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' )
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 ( '登錄失敗!' ) } } )
2.3.6 判斷用戶輸入的密碼是否正確
核心實現思路:調用bcrypt.compareSync(用戶提交的密碼,數據庫中的密碼)方法比較密碼是否一致。 返回值是布爾值。
const compareResult
= bcrypt
. compareSync ( userinfo
. password
, results
[ 0 ] . password
) if ( ! compareResult
) { return res
. cc ( '登陸失敗!' ) }
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包
const jwt
= require ( 'jsonwebtoken' )
創建config.js文件,并向外共享加密和還原Token的jwtSecretKey字符串
module
. exports
= { jwtSecrecKey : 'lingyuancong'
}
將用戶信息對象加密成Token字符串
const config
= require ( '../config' )
const tokenStr
= jwt
. sign ( user
, config
. jwtSecrecKey
, { expiresIn : '10h' ,
} )
將生成的Token字符串響應給客戶端:
const tokenStr
= jwt
. sign ( user
, config
. jwtSecretKey
, { expiresIn : config
. expiresIn
, } ) res
. send ( { status : 0 , msg : '登陸成功!' , token : 'Bearer ' + tokenStr
, } )
配置解析Token的中間件
運行如下的命令,安裝解析Token的中間件:
npm i express-jwt@5.3.3
在app.js中注冊路由之前,配置解析Token的中間件:
const config
= require ( './config' )
const expressJWT
= require ( 'express-jwt' )
在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路由模塊,并初始化如下的代碼結構
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' )
app
. use ( '/my' , userinfoRouter
)
3.1.2 初始化路由處理函數模塊
創建/router_handler/userinfo.js路由處理模塊,并初始化如下的代碼結構:
exports
. getUserInfo = ( req, res ) => { res
. send ( 'ok' )
}
修改/router/userinfo.js中的代碼
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語句:
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 ) => {
const sql
= ` select id, username, nickname, email, user_pic from ev_users where id=? `
db
. query ( sql
, req
. body
. id
, ( err, results ) => { if ( err
) return res
. cc ( err
) 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的驗證規則如下:
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
, [ 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 ( '用戶不存在!' ) } )
}
判斷提交的就密碼是否正確:
const compareResult
= bcrypt
. compareSync ( userinfo
. password
, results
[ 0 ] . password
) if ( ! compareResult
) { return res
. cc ( '原密碼錯誤!' ) }
對新密碼進行加密,更新到數據庫:
const sql
= ` update ev_users set password=? where id=? ` const newPwd
= bcrypt
. hashSync ( req
. body
. newPwd
, 10 ) 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的驗證規則如下:
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项目 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。