node系列之?dāng)?shù)據(jù)接口注冊(cè)登陸接口的實(shí)現(xiàn)
1、使用express腳手架創(chuàng)建項(xiàng)目
2、了解項(xiàng)目的目錄結(jié)構(gòu)
3、準(zhǔn)備數(shù)據(jù)庫(kù)相關(guān)文件
4、編寫注冊(cè)接口
5、編寫登陸接口
6、驗(yàn)證登陸實(shí)現(xiàn)
7、預(yù)告
1、使用express腳手架創(chuàng)建項(xiàng)目
// 安裝腳手架,只需安裝一次
npm i express-generator -g
// 創(chuàng)建express項(xiàng)目
express myapp --view=ejs
cd myapp
// 安裝依賴
npm i
// 安裝需要使用的模塊
// 數(shù)據(jù)庫(kù)模塊 用戶唯一id模塊 密碼加密模塊 token模塊
npm i mongoose node-uuid bcryptjs jsonwebtoken -S
2、了解項(xiàng)目的目錄結(jié)構(gòu)
bin
www ------- 服務(wù)器啟動(dòng)
node_modules ------- 項(xiàng)目的依賴文件
public ------- 靜態(tài)資源文件夾
images ------- 靜態(tài)圖片
javascripts ------- 靜態(tài)的js文件
stylesheets ------- 靜態(tài)的樣式表文件
routes ------- 路由文件
index.js ------- 默認(rèn)的路由
users.js ------- 用戶相關(guān)的路由
views ------- 路由對(duì)應(yīng)的頁(yè)面
index.ejs ------- 默認(rèn)的首頁(yè)
error.ejs ------- 錯(cuò)誤頁(yè)面
app.js ------- 使用中間件,注冊(cè)路由
package.json ------- 描述文件
3、準(zhǔn)備數(shù)據(jù)庫(kù)相關(guān)文件
大勛在node系列之?dāng)?shù)據(jù)庫(kù)mongoose的封裝中給大家介紹了如何封裝mongoose,可以先行查看如何封裝,封裝的文件夾為sql,如果不想看的,可以直接通過(guò)網(wǎng)盤下載該文件夾
將該sql文件放置項(xiàng)目的跟目錄下
- myapp
- sql
- collection
users.js
db.js
index.js
4、編寫注冊(cè)接口
目標(biāo)文件: myapp/routes/users.js
實(shí)現(xiàn)思路:使用post提交數(shù)據(jù)的方式,先以手機(jī)號(hào)查詢有沒有該用戶,如果有該用戶,提示用戶該賬號(hào)已經(jīng)注冊(cè)過(guò)了;如果沒有該用戶,則可以完成注冊(cè),首先得將密碼加密,加密完成后插入數(shù)據(jù)庫(kù)
代碼實(shí)現(xiàn):
// 找到用戶集合
var User = require('./../sql/collection/users');
// 找到數(shù)據(jù)庫(kù)封裝文件
var sql = require('./../sql');
// 狀態(tài)碼的封裝
var utils = require('./../utils')
// 用戶唯一標(biāo)識(shí)的id
var uuid = require('node-uuid');
// 密碼加密模塊
var bcrypt = require('bcryptjs');
var salt = bcrypt.genSaltSync(10); // 加密級(jí)別
// 實(shí)現(xiàn)注冊(cè)接口 -- post提交方式
router.post('/register', (req, res, next) => {
// 1、先獲取表單信息
let { username, password, tel } = req.body;
// 2、根據(jù)手機(jī)號(hào)查詢 用戶集合中是否有該用戶,如果有,返回有該賬戶,如果沒有注冊(cè)繼續(xù)
sql.find(User, { tel }, { id: 0 }).then(data => {
// 2.1 判斷有沒有該用戶
if (data.length === 0) {
// 2.2 沒有該用戶----繼續(xù)完成注冊(cè)操作
// 2.2.1 生成用戶的id
let userid = 'users' + uuid.v1();
// 2.2.2 對(duì)密碼加密
password = bcrypt.hashSync(password, salt)
// 2.2.3 插入數(shù)據(jù)庫(kù)
sql.insert(User, { userid, username, password, tel}).then(() => {
res.send(utils.registersuccess)
})
} else {
// 2.3 已有該用戶
res.send(utils.registered)
}
})
})
附 狀態(tài)碼封裝模塊 myapp/utils/index.js
module.exports = {
registered: {
code: '10000',
message: '該用戶已注冊(cè),請(qǐng)直接登錄'
},
registersuccess: {
code: '10101',
message: '注冊(cè)成功'
}
}
5、編寫登陸接口
目標(biāo)文件 myapp/routes/users.js
實(shí)現(xiàn)思路:根據(jù)手機(jī)號(hào)查詢有沒有該用戶,如果沒有,提示用戶未注冊(cè),如果有該用戶,使用bcryptjs模塊驗(yàn)證密碼的有效性,如果有效,生成token,返回給前端相應(yīng)的token值。
var jwt = require('jsonwebtoken');
// 實(shí)現(xiàn)登陸功能
router.post('/login', (req, res, next) => {
// 1、獲取表單信息
let { tel, password } = req.body;
// 2、依據(jù)手機(jī)號(hào)查詢有沒有該用戶
sql.find(User, { tel }, { _id: 0 }).then(data => {
// 2.1 判斷有么有該用戶
if (data.length === 0) {
// 2.2 沒有該用戶
res.send(utils.unregister)
} else {
// 2.3 有該用戶,驗(yàn)證密碼
// 2.3.1 獲取數(shù)據(jù)庫(kù)中的密碼
let pwd = data[0].password;
// 2.3.2 比較 輸入的 密碼和數(shù)據(jù)庫(kù)中的密碼
var flag = bcrypt.compareSync(password, pwd) // 前為輸入,后為數(shù)據(jù)庫(kù)
if (flag) {
// 2.3.3 密碼正確,生成token
let userid = data[0].userid
let username = data[0].username
let token = jwt.sign({ userid, username }, 'daxunxun', {
expiresIn: 606024// 授權(quán)時(shí)效24小時(shí)
})
res.send({
code: '10010',
message: '登陸成功',
token: token
})
} else {
// 2.3.4 密碼錯(cuò)誤
res.send({
code: '10100',
message: '密碼錯(cuò)誤'
})
}
}
})
})
6、驗(yàn)證登陸實(shí)現(xiàn)
目標(biāo)文件: myapp/app.js
實(shí)現(xiàn)思路:很多的數(shù)據(jù)請(qǐng)求都需要登陸之后才能獲取到,在此統(tǒng)一封裝驗(yàn)證登陸
// 引入token模塊
var jwt = require('jsonwebtoken');
// 全局的路由匹配
app.use((req, res, next) => {
// 排除登陸注冊(cè)頁(yè)面
if (req.url !== '/users/login' && req.url !== '/users/register') {
// 不同形式獲取token值
let token = req.headers.token || req.query.token || req.body.token;
// 如果存在token ---- 驗(yàn)證
if (token) {
jwt.verify(token, 'daxunxun', function(err, decoded) {
if (err) {
res.send({
code: '10119',
message: '沒有找到token.'
});
} else {
req.decoded = decoded;
console.log('驗(yàn)證成功', decoded);
next()
}
})
} else { // 不存在 - 告訴用戶---意味著未登錄
res.send({
code: '10119',
message: '沒有找到token.'
});
}
} else {
next()
}
})