iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 15
2
Modern Web

Node JS-Back end見聞錄系列 第 15

Node.js-Backend見聞錄(14):實作-會員系統(三)-會員登入

Node.js-Backend見聞錄(14):實作-會員系統(三)-會員登入

前言

會員系統的部分,我們已經完成第一部分「會員註冊」的功能了。接續往「會員登入」的功能出發。

會員登入需求

  • 提供一個登入的API。若登入成功給予token,若無則出現警示。

套件

$ npm install jsonwebtoken

資料結構

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
├── 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

驗證帳號密碼是否正確

為了驗證帳號密碼是否正確,這意謂著我們要先把client端的資料取出,並將取出的資料與資料庫的資料做比對。先修改在models資料夾中的login_model.js檔案。

const db = require('./connection_db');

module.exports = function memberLogin(memberData) {
    let result = {};
    return new Promise((resolve, reject) => {
        // 找尋
        db.query('SELECT * FROM member_info WHERE email = ? AND password = ?', [memberData.email, memberData.password], function (err, rows) {
            if (err) {
                result.status = "登入失敗。"
                result.err = "伺服器錯誤,請稍後在試!"
                reject(result);
                return;
            }
            resolve(rows);
        });
    });
}

之後,接續修改在controllers資料夾中的modify_controller.js檔案。我們先新增一個function,而這個function是專門處理login的動作。

loginAction(memberData).then(rows => {
    if (check.checkNull(rows) === true) {
        res.json({
            result: {
                status: "登入失敗。",
                err: "請輸入正確的帳號或密碼。"
            }
        })
    } else if (check.checkNull(rows) === false) {
        res.json({
            result: {
                status: "登入成功。",
                loginMember: "歡迎 " + rows[0].name + " 的登入!",
            }
        })
    }
})

當中check的checkNull,則是我們在service資料夾的member_check.js檔案中新增了一個可以辨識空值的判斷:

    //判斷空值
    checkNull(data) {
        for (var key in data) {
            // 不為空
            return false;
        }
        // 為空值
        return true;
    }

最後,修改routes資料夾的member.js檔案。新增一個API URL為/login給登入這功能專用。

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);

module.exports = router;

測試

我們一樣透過Postman來幫我們做測試:

  • API URL: localhost:3000/login
  • HTTP method: POST
  • 傳輸格式:w-xxx-form-urlencoded

其結果:

接續測試錯誤的密碼試試看:

  • API URL: localhost:3000/login
  • HTTP method: POST
  • 傳輸格式:w-xxx-form-urlencoded

其結果:

若帳號成功則給token

Token部分我們需要用到前面所提到套件jsonwebtoken,透過它來幫我們產生token。由於token可以設置時間限制,也就是時間一到就會過期。而這次的範例中,我們先使用1小時作為一個期限,並將使用者的id資料也跟著放進去token的生成規則中。最後,再把token的值塞入response的header中,且取名為token

首先,我們先修改Node.js-Backend見聞錄(12):實作-會員系統(一)-會員註冊(一)中提到的config資料夾的development_config.js檔案。

註記:這是因為我們在 token 部分接續會使用到 secret。而 secret 算是敏感性資料之一。所以我們會搭配.env的檔案來將環境變數藏匿於該檔案中。

require('dotenv').config()

module.exports = {
    mysql: {
      host: process.env.HOST,
      user: process.env.DATABASE_USER,
      password: process.env.DATABASE_PASSWORD,
      database: process.env.DATABASE
    },
    secret: process.env.MY_SECRET
}

並接續修改.env檔案,將MY_SECRET放置其中。

HOST = 'localhost'
DATABASE_USER = 'test'
DATABASE_PASSWORD = '1234'
DATABASE = 'member'
MY_SECRET = 'secret'

最後再修改controllers資料夾的modify_controller.js檔案:

loginAction(memberData).then(rows => {
    if (check.checkNull(rows) === true) {
        res.json({
            result: {
                status: "登入失敗。",
                err: "請輸入正確的帳號或密碼。"
            }
        })
    } else if (check.checkNull(rows) === false) {
        // 產生token
        const token = jwt.sign({
            algorithm: 'HS256',
            exp: Math.floor(Date.now() / 1000) + (60 * 60), // token一個小時後過期。
            data: rows[0].id
        }, config.secret);
        res.setHeader('token', token);
        res.json({
            result: {
                status: "登入成功。",
                loginMember: "歡迎 " + rows[0].name + " 的登入!",
            }
        })
    }
})

註記:將會員的id放進去token的生成規則中,這步驟是為了在下個實作「會員資料」中,如果會員想修改自己的資料,可以根據token來反推出是哪個會員的id,透過這個id就能指定資料庫要修改哪筆會員資料。

測試

我們一樣透過Postman來幫我們做測試:

  • API URL: localhost:3000/login
  • HTTP method: POST
  • 傳輸格式:w-xxx-form-urlencoded

其結果:

我們就能看到產生出來的token就藏在response的headers的token欄位中。

小結

這在我們已經完成了「會員登入」的功能了,接下來會往「修改會員資料」部分前進。


上一篇
Node.js-Backend見聞錄(13):實作-會員系統(二)-會員註冊(二)
下一篇
Node.js-Backend見聞錄(15):實作-會員系統(四)-會員資料
系列文
Node JS-Back end見聞錄31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言