會員系統的部分,我們已經完成第二部分「會員登入」的功能了。接續往「修改會員資料」的功能出發。
在models
資料夾新增個login_model.js
的檔案。
.
├── app.js
├── bin
│ └── www
├── config
│ └── development_config.js
├── controllers
│ └── modify_controller.js
├── models
│ ├── connection_db.js
│ ├── encryption_model.js
│ ├── login_model.js
│ ├── register_model.js
│ ├── update_model.js
│ └── verification_model.js
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── member.js
│ └── users.js
├── sevice
│ └── member_check.js
├── views
├── error.ejs
└── index.ejs
├── .env
└── .gitignore
從第一個需求推估若要達到這個功能,會員必須要先登入才能進行更換資料的動作。且在上篇文章中,已經實作出token功能。所以我們第一步要先做出能夠驗證會員的功能,也就是看針對token來做個驗證的動作。
在上篇產生token
的部分中,我們有故意將id
也塞進去。藉由反推token
的動作,可以從中取出id
,等同於我們只要針對這個id的資料來進行更改動作即可。
首先,我們先寫一個驗證token
及透過token
來反推id
的功能。在models
資料夾的verification
檔案中寫入:
const jwt = require('jsonwebtoken');
const config = require('../../config/development');
//進行token認證
module.exports = function verifyToken(token) {
let tokenResult = "";
const time = Math.floor(Date.now() / 1000);
return new Promise((resolve, reject) => {
//判斷token是否正確
if (token) {
jwt.verify(token, config.secret, function (err, decoded) {
if (err) {
tokenResult = false;
resolve(tokenResult);
//token過期判斷
} else if (decoded.exp <= time) {
tokenResult = false;
resolve(tokenResult);
//若正確
} else {
tokenResult = decoded.data
resolve(tokenResult);
}
})
}
});
}
等同於要是今天token發生錯誤或過期就會回傳false
。反之,則回傳反推過後的id
值。接續來實作更改會員資料的資料庫功能。
再來接續到controllers
資料中的modify_controller.js
檔案來新增一個postUpdate
的funciton:
postUpdate(req, res, next) {
const token = req.headers['token'];
//確定token是否有輸入
if (check.checkNull(token) === true) {
res.json({
err: "請輸入token!"
})
} else if (check.checkNull(token) === false) {
verify(token).then(tokenResult => {
if (tokenResult === false ) {
res.json({
result: {
status: "token錯誤。",
err: "請重新登入。"
}
})
} else {
res.json({
test: "token正確"
})
}
})
}
}
給予這個API一個新的URL的端口,好讓我們能測試驗證token的部分是否能正常運作。在routes
資料夾的member.js
檔案中寫入:
var express = require('express');
var router = express.Router();
const MemberModifyMethod = require('../controllers/modify_controller');
memberModifyMethod = new MemberModifyMethod();
router.post('/register', memberModifyMethod.postRegister);
router.post('/login', memberModifyMethod.postLogin);
router.put('/update', memberModifyMethod.putUpdate);
module.exports = router;
來測試看看token是否能正常進行判斷,這邊我們依舊使用Postman來運行。先透過呼叫/login
的API來取得token。之後我們在使用token的值來做測試:
login
API取得的token值)發現token
偵測後是正確的,且id
值也有成功被反推出來。
接續我們嘗試隨便更動token
中其中的字母試試看會不會出錯:
其結果是符合我們預期的。
id
部分已經在上個動作完成反推動作。接續就實作跟資料庫做聯動的部分:
在models
資料夾中新增一個update_model.js
的檔案,並寫入:
const db = require('./connection_db');
module.exports = function customerEdit(id, memberUpdateData) {
let result = {};
return new Promise((resolve, reject) => {
db.query('UPDATE member_info SET ? WHERE id = ?', [memberUpdateData, id], function (err, rows) {
if (err) {
console.log(err);
result.status = "會員資料更新失敗。"
result.err = "伺服器錯誤,請稍後在試!"
reject(result);
return;
}
result.status = "會員資料更新成功。"
result.memberUpdateData = memberUpdateData
resolve(result)
})
})
}
接著將controllers
資料夾的modify_controller.js
檔案中,其putUpdate
function修改成:
putUpdate(req, res, next) {
const token = req.headers['token'];
//確定token是否有輸入
if (check.checkNull(token) === true) {
res.json({
err: "請輸入token!"
})
} else if (check.checkNull(token) === false) {
verify(token).then(tokenResult => {
if (tokenResult === false) {
res.json({
result: {
status: "token錯誤。",
err: "請重新登入。"
}
})
} else {
const id = tokenResult;
// 進行加密
const password = encryption(req.body.password);
const memberUpdateData = {
name: req.body.name,
password: password,
update_date: onTime()
}
updateAction(id, memberUpdateData).then(result => {
res.json({
result: result
})
}, (err) => {
res.json({
result: err
})
})
}
})
}
}
接續,我們使用之前第一個成功註冊的會員,其name為test
,來進行測試:
先進入/login
API來取得token
值。待取得後,將token
值記錄下來並呼叫/update
的API,這部分我們一樣藉由Postman來協助測試,並將其會員的name從test
改為test1
試試:
login
API取得的token值)修改完成後,我們再到terminal去進到MySQL那邊來輸入select * from member_info;
指令,來觀察看看id
為1的會員其name
值有沒有變成test1。
其結果是有的,代表我們更改會員資料成功。
這在我們已經完成了「修改會員資料」的功能了,接下來我們再來將「會員系統」這部分做個收尾,並添加些不一樣的功能。
token判斷那邊都是resolve,
這樣會沒有rejection的狀態吧?
Hi, ip258852謝謝你的回覆。
是的,token判斷那部分只使用resolve
來處理,反倒沒有使用reject
。
在「判斷token是否正確」這部分model
中verification.js
的處理方式為3種情況,分別是:
且都是用promise的resolve
方式來進行回傳,並沒有再額外使用reject
的方式來回傳錯誤的狀態。
等同於這部分的處理,在controller
中modify_controller.js
是直接沿用resolve
的值來進行更進一步的判斷。
但若是要運用promise的reject
的話,寫法就會變成:
const jwt = require('jsonwebtoken');
const config = require('../../config/development');
//進行token認證
module.exports = function verifyToken(token) {
let tokenResult = '';
const time = Math.floor(Date.now() / 1000);
return new Promise((resolve, reject) => {
//判斷token是否正確
if (token) {
jwt.verify(token, config.secret, function (err, decoded) {
if (err) {
reject('token錯誤');
//token過期判斷
} else if (decoded.exp <= time) {
reject('token已過期');
//若正確
} else {
tokenResult = decoded.data
resolve(tokenResult);
}
})
}
});
}
postUpdate(req, res, next) {
const token = req.headers['token'];
//確定token是否有輸入
if (check.checkNull(token) === true) {
res.json({
err: "請輸入token!"
})
} else if (check.checkNull(token) === false) {
verify(token).then(tokenResult => {
res.json({
result: {
status: 'token正確',
}
})
}, (err) => {
res.json({
err
})
})
}
}
這樣的寫法也能達到在文章中所提到的效果。
OK 懂了
3Q