สร้างระบบยืนยันตัวตนง่าย ๆ ไว้ใช้กับเว็บตัวเอง04 September 2020Programing

สร้างระบบยืนยันตัวตนง่าย ๆ ไว้ใช้กับเว็บตัวเอง

หากว่าคุณมีเว็บไซต์ส่วนตัวไม่ว่าจะของบริษัท หรือระบบใด ๆ ก็แล้วแต่ที่ต้องใช้คนเข้าร่วมจำนวนมาก การสร้างระบบยืนยันตัวตนขึ้นมานั้นถือเป็นสิ่งสำคัญ เพราะในโลกปัจจุบันระบบความปลอดภัยถือเป็นเรื่องหลักในการจะทำเครือข่าย หรือระบบใด ๆ สักอย่างหนึ่ง ทั้งนี้ที่สำคัญมาก ๆ ก็เพื่อปกป้องฐานข้อมูลของบริษัทด้วย ในปัจจุบันการยืนยันตัวตนนั้นมีหลายอย่าง ไม่ว่าจะต้องยืนยันตัวด้วยลายนิ้วมือ (แบบในโทรศัพท์มือถือ) ยืนยันตัวด้วยใบหน้า หรือการกรอกรหัส โค้ดลับต่าง ๆ ก็ได้เช่นกัน

ในหัวข้อนี้จะเป็นการตัวอย่างง่ายๆ ในการทำระบบ Authentication ด้วยภาษา Nodejs ซึ่งจะยกตัวอย่างในการทำระบบ Register และ Login เพื่อเข้าสู่เว็บไซต์ มาเริ่มกันเลย!

เครื่องมือในการใช้งาน

  1. Nodejs
  2. Bcrypt
  3. Mysql
  4. Expressjs
  5. Jwt

มาเริ่มทำระบบกัน

npm init -y
  1. พิมพ์คำสั่งสำหรับเริ่มต้นโปรเจ็ค หลังจากนั้นเราจะได้รับไฟลล์ pakeage.json และให้เราสร้างไฟล์ app.js
{
  "name": "authenNodejs",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node app.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

2. ให้เราเพิ่มคำสั่ง start ใน scripts เป็น node app.js

npm install express bcrypt mysql2 jsonwebtoken

3. ติดตั้ง package เพิ่มเติมคือ express, bcrypt, mysql2 และ jsonwebtoken

ต่อมาคือผมสร้าง Structrue ของ Project ผมแบ่งออกเป็น 4 ส่วนคือ controller, db, route, model โอเคเรามาดูที่ละส่วนกันเริ่มจาก db ซึ่งผมเขียนสำหรับต่อกับ database mysql

const db = require('mysql2')

const Database = db.createPool({
    host:'127.0.0.1',
    user:'root',
    database:'user',
    password:'root',
    port:8889
})

module.exports = Database.promise();

4. ซึ่งผมเขียนต่อ mysql ดังนี้เป็น db ที่ running ใน localhost นะ

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

class UserModel {
    constructor({email='', password='', id=0}) {
        this.email = email;
        this.password = password;
        this.id = id;
        this.createAt = new Date();
        this.updateAt = new Date();
    }

    registerUser() {
        return db.execute('INSERT INTO USER (email, password, createAt, updateAt) VALUES(?, ?, ?, ?)',
        [this.email, this.password, this.createAt, this.updateAt])
    }
    static findUserByEmail ({email=''}) {
        return db.execute('SELECT * FROM USER WHERE user.email = ?',[email])
    }

}

module.exports = UserModel;

5. ต่อมาส่วนของ Model ซึ่งผมจะเอาไว้คุยกับ db อีกที ใน Class UserModel ผมสร้าง registerUser สำหรับเพิ่มข้อมูลเข้าไปใน db และก็findUserByEmail สำหรับหา User

const bcrypt = require('bcrypt');
const UserModel = require('../model/userModel');

exports.registerController = (req, res, next) => {
    const { email, password} = req.body;
    bcrypt.hash(password, 10)
        .then((hash) => {
            const User = new UserModel({email:email ,password: hash})
            User.registerUser()
                .then(() => {
                    res.status(201)
                    .json({
                        message:'success'
                    })
                }).catch((error) => {
                    res.status(500)
                        .json({
                            message:error
                        })
                })
        })
        .catch((error) => {
            res.status(500)
            .json({
                message:error
            })
        })
}

6. ส่วนของ Controller ผมแบ่งเป็น 2 ส่วนนะ 1 คือ register และ 2 login ในส่วนของ register ผมรับ email, password มาจาก request แล้วก็นำ password ไปเข้ารหัสโดยใช้ function hash ที่มาจาก packeage bcrypt หลังจากนั้นก็บันทึกลง db ที่เราเขียนไว้ใน model

exports.loginController = (req, res, next) => {
    const { email='', password} = req.body;
    UserModel.findUserByEmail({email:email})
        .then(([row]) => {
            if(row.length !== 0) {
                return bcrypt.compare(password, row[0].password)
                    .then((result) => {
                        if(!result) {
                            res.status(401)
                                .json({
                                    message: "Authentication failed"
                                })
                        } else {
                            let jwtToken = jwt.sign({
                                email: row[0].email,
                                userId: row[0].id
                            }, 
                            "create-authen-nodejs", {
                                expiresIn: "1h"
                            });
                            res.status(200).json({
                                token: jwtToken,
                                expiresIn: 3600,
                            });
                        }
                    }).catch((error) => {
                        res.status(401)
                            .json({
                                message: "Authentication failed",
                                error:error
                            })
                    })
            } else {
                res.status(401)
                .json({
                    message: "Authentication failed"
                })
            }
        })
        .catch((error) => {
            res.status(500)
            .json({
                message:error
            })
        })
}

7. ในส่วนของ loginController รับ request email, password มา สิ่งแรกที่ผมทำคือเช็คใน db ว่ามี email นี้ไหมถ้ามีก็นำ password ที่มาจาก body และ password ที่เข้ารหัส hash มา compare ด้วย function compare ถ้าตรงกันก็จะพบข้อมูลไม่ตรงก็ดีดออกจากระบบทันที หลังจากที่ได้ compare แล้วตรงกันก็นำมาเข้าสร้าง Token ด้วย function sign ซึ่งในนี้ผมใส่ 3 parameter อันแรกคือ Object ของ playload ผมใส่ email, id อันที่ 2 คือ secret key ซึ่งจะเอาไว้ใช้สำหรับให้ ฝั่ง client คุยกับ backend ถ้าเกิดใช้คนละ secret key ก็ไม่สามารถใช้งานได้ และสุดท้ายคือ อายุของ token ผมเซ็ตไว้ที่ 1 ชั่วโมง หลังจากนั้นก็ response token. secret key ควรเป็น ENV ไว้น่ะห้ามบอกใครเด็ดขาด

ทดลอง

register ด้วย email และ password

ทดลอง login และก็จะได้ token ที่เรา response ออกมา

ข้อมูล user ที่ผมเก็บไว้ใน db

สรุป

การทำ authentication มีขั้นการตอนการทำงานไม่กี่ขั้นตอน คือ สร้างผู้ใช้งานและนำรหัสผ่านไปเข้ารหัสและบันทึกไว้ เมื่อจะใช้งานก็นำรหัสผ่านที่บันทึกไว้มาเปรียบเทียบกับรหัสที่ยังไม่โดนเข้ารหัสด้วยฟังชันก์ของตัว package และเมื่อรหัสถูกต้องก็ใช้ jwt sign เพื่อเขียน token ออกมา
แล้วหลังจากได้ Token แล้วเราจะนำไปใช้งานต่อยังไงละ คือเมื่อเราได้รับ token เราก็นำ token นี้เเละแนบไปกับ header เวลาที่ต้องคุยกับ api ในฝั่ง backend เองก็ต้องทำ midleware สำหรับ authen route เมื่อมีการติดต่อเข้ามาเหมือนกัน เดี๋ยวเราจะไปคุยกับ EP หน้านะครับ

https://github.com/najaroen/node-auth-example

แต่หากใครเริ่มคิดว่ามันยาก หรือต้องการระบบยืนยันตัวที่คิดว่าปลอดภัยได้มากกว่านี้ให้กับระบบของตัวเอง ก็ทักมาพวกเราได้ หรือจะจ้างให้พวกเราทำระบบนั้นดูก็ได้ครับ มาคุยกันก่อนได้เลย

Twinsynergy #ออกและพัฒนาเว็บไซต์ #ทำเว็บไซต์และแอปพลิเคชั่น #พัฒนาซอฟแวร์ #Website #MobileApplication #Dev #WebDesign

📌สนใจติดต่อ📌
💻 https://area51.twinsynergy.co.th
📱 063-789-9059

ก่อนหน้า
ถัดไป