วิธีสร้าง Authentication ด้วย NodeJS

0
Tik01

ในหัวข้อนี้จะเป็นการตัวอย่างง่ายๆ ในการทำระบบ 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

LEAVE A REPLY

Please enter your comment!
Please enter your name here

five × four =