DEV Community

Bhurisub Dejpipatpracha
Bhurisub Dejpipatpracha

Posted on • Edited on

1 2

Node.js : ระบบ Authentication แบบพื้นฐานด้วยมอดูล Passport-local

บทความนี้จะขอแนะนำการเขียนสคริปต์ JavaScript เพื่อทำระบบ Authenticationแบบพื้นฐาน ด้วยมอดูล Passport จะช่วยให้ระบบสามารถตรวจสอบสมาชิกก่อนที่เข้าใช้งานระบบสมาชิกได้ โดยมอดูล passport จะช่วยตรวจสอบ Username และ Password ได้ทั้งแบบพื้นฐาน ผ่าน Account ของฐานข้อมูลของเรา ผ่าน Account ของ Facebook ผ่าน Account ของ Twitter ฯลฯ

ซึ่งในตัวอย่างนี้จะแนะนำการเขียนสคริปต์ทั้งแบบพื้นฐาน คือ นำชื่อผู้ใช้และรหัสผ่านใส่ไว้ในสคริปต์ เพื่อทำความเข้าใจหลักการใช้งานมอดูล Passport

โดยเริ่มจากติดตั้งมอดูล express, ejs, express, express-session, passport, passport-local

npm i cookie-parser
npm i ejs
npm i express
npm i express-session
npm i passpost
npm i passport-local

สคริปต์ views/login.ejs สร้างฟอร์มรับข้อมูล login ฟอร์ม login

<!DOCTYPE html>
<html>
  <head>
    <title>:: Login ::</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="./bootstrap/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>
      <div class="container">
          <div class="page-header">
              <h1>:: Login ::</h1>
              <hr>
          </div>
          <div class="row">
            <div class="col">
              <form method="post" action="login">
                <div class="form-group">
                  <label for="user">Username</label>
                  <input type="text" class="form-control" name="username" 
                    placeholder="Username" required>
                </div>
                <div class="form-group">
                  <label for="pass">Password</label>
                  <input type="text" class="form-control"name="password" 
  placeholder="Password" required>
                </div> 
                <button type="submit" class="btn btn-primary">Login</button>
                <button type="reset" class="btn btn-primary">Reset</button>
              </form>
            </div>
          </div>
        </div>
    <script src="./jquery.min.js"></script>
    <script src="./bootstrap/js/bootstrap.min.js"></script>
  </body>
</html>

สคริปต์ views/home.ejs หน้าหลักหลังจากผ่านการ login เข้ามาแล้ว

<!DOCTYPE html>
<html>
  <head>
    <title>:: Home ::</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="./bootstrap/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>
      <div class="container">
          <div class="row">
            <h1>:: Home ::</h1>
          </div>
          <div class="row">
             Login Ok.<br/><br/> 
             Users -> <%=_id%> <%=fname%> <%=lname%> <br/><br/>
          </div>
          <div class="row">
            <a href='./logout'>Logout</a>
          </div>
        </div>
    <script src="./jquery.min.js"></script>
    <script src="./bootstrap/js/bootstrap.min.js"></script>
  </body>
</html>

สคริปต์ index.js เป็นสคริปต์หลักของงานนี้

const express = require('express')
const app = express()
app.use(express.static(__dirname + '/public'))
app.set('view engine', 'ejs')

const passport = require('passport')
const LocalStrategy = require('passport-local').Strategy

const bodyParser = require('body-parser')
const cookieParser = require('cookie-parser')
app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())
app.use(cookieParser())

const session = require('express-session')
app.use(session({ secret: 'I am Anakin.', resave: true, saveUninitialized: true }))
app.use(passport.initialize())
app.use(passport.session())

passport.use(new LocalStrategy((username, password, done) => {
    if(username =="admin" && password=="1234") {
        user = {    
            _id : 1,
            fname : "Anakin ",
            lname : "Skywalker"
        }
        console.log('Correct Password.')
        return done(null,user)
    } else {
        console.log('Incorrect password.')
        return done(null, false, { message: 'Incorrect password.' })
    }
}))

passport.serializeUser((user, done) => {
    console.log('SerializeUser')
    done(null, user) 
})

passport.deserializeUser((user, done) => {
    console.log('DeserializeUser')
    done(null, user) 
})

app.get('/', (req, res) =>  {
    res.render('login')
})

app.post('/login', passport.authenticate('local', { 
    successRedirect: '/home',
    failureRedirect: '/' 
}))

function isLoggedIn(req, res, next) {
    if (req.isAuthenticated()) {
        return next()
    } else {
        res.redirect('/')
    }
}

app.get('/home',isLoggedIn,(req,res) => {
    res.render('home',req.user)
})

app.get('/logout',(req,res) => {
    req.logout()
    res.redirect('/')
})

app.listen(3000, () => {
    console.log('Server Started on localhost:3000...')
})

เราต้องเรียกใช้มอดูล passport เก็บไว้ในตัวแปร passport และเรียกใช้มอดูล passport-local เก็บไว้ในตัวแปร LocalStrategy สำหรับใช้ตรวจสอบผู้ใช้และรหัสผ่านแบบพื้นฐานได้

const passport = require('passport') 
const LocalStrategy = require('passport-local').Strategy

เรียกใช้มอดูล express-session เก็บไว้ในตัวแปร session สำหรับเก็บข้อมูลที่เก็บหลังจากตรวจสอบผู้ใช้และรหัสผ่านเรียบร้อยแล้ว

const session = require('express-session')
app.use(session({ secret: 'I am Anakin.', resave: true, saveUninitialized: true }))
app.use(passport.initialize())
app.use(passport.session())

กำหนดให้มอดูล password ใช้งานการตรวจสอบแบบ Local โดยนำชื่อผู้ใช้ที่อยู่ในตัวแปร username และ รหัสผ่านในตัวแปร password นำมาตรวจสอบแบบง่าย ซึ่งหากผู้ใช้ป้อนมาไม่ถูกต้องก็แสดงข้อความไม่ถูกต้อง และหากตรวจสอบแล้วผู้ใช้ป้อนข้อมูลมาถูกต้อง ก็กำหนดข้อมูลที่จะเก็บไว้ใน Session เพื่อเรียกใช้งานภายหลังได้ โดยในตัวอย่างนี้จะเก็บข้อมูล _id,fname,lname เก็บไว้ในตัวแปร user

passport.use(new LocalStrategy((username, password, done) => {
    if(username =="admin" && password=="1234") {
        user = {    
            _id : 1,
            fname : "Anakin ",
            lname : "Skywalker"
        }
        console.log('Correct Password.')
        return done(null,user)
    } else {
        console.log('Incorrect password.')
        return done(null, false, { message: 'Incorrect password.' })
    }
}))

เป็นการกำหนดว่าจะนำข้อมูลอะไรไปเก็บไว้ใน Session หลังจากผ่าน Login มาเรียบร้อบแล้ว

passport.serializeUser((user, done) => {
    console.log('SerializeUser')
    done(null, user) 
})

เป็นการกำหนดว่าจะนำข้อมูลออะไรใน Session ออกมาใช้งาน ซึ่งจะใช้ในหน้าเว็บเพจต่างๆ ที่สมาชิกเข้าถึงได้

passport.deserializeUser((user, done) => {
    console.log('DeserializeUser')
    done(null, user) 
})

ที่กล่าวไว้ข้างต้นจะเป็นการกำหนดค่าสำหรับใช้งานมอดูล passport-local ซึ่งรันหน้าแรก / ก็จะแสดงฟอร์ม Login เพื่อรับ Username และ Password จากผู้ใช้ ซึ่งข้อมูลทั้งหมดก็จะส่งมายัง /login เพื่อทำการตรวจสอบข้อมูล หากข้อมูลถูกต้องก็จะส่งไปหน้า /home และหากข้อมูลไม่ถูกต้องก็ย้อนกลับไปหน้าฟอร์ม login

app.get('/', (req, res) =>  {
    res.render('login')
})

app.post('/login', passport.authenticate('local', { 
    successRedirect: '/home',
    failureRedirect: '/' 
}))

ในระบบสมาชิกก็จะมีส่วนที่สมาชิกเข้าถึงได้หลายหน้า แต่ละหน้าก่อนจะเข้าไปใช้งานได้ต้องผ่านการตรวจสอบมาก่อนว่า ได้ผ่านการ Login มาแล้วหรือไม่ โดยเราจะสร้างฟังก์ชันชื่อ isLoggedIn()เอาไว้ตรวจสอบ โดย method ชื่อ isAuthenticated() เป็นตัวหลักในการตรวจสอบการ login ซึ่งหากผ่านการตรวจสอบแล้วก็ไปในขั้นตอนต่อไป แต่หากไม่ผ่านการตวจสอบก็จะกลับไปยังฟอร์มหน้า login

function isLoggedIn(req, res, next) {
    if (req.isAuthenticated()) {
        return next()
    } else {
        res.redirect('/')
    }
}

ไปหน้าหลักของสมาชิก แล้วแสดงข้อมูลสมาชิกออก user

app.get('/home',isLoggedIn,(req,res) => {
    res.render('home',req.user)
})

หากต้องการออกจากระบบก็จะต้องทำการ logout() และกลับไปหน้า Login ต่อไป

app.get('/logout',(req,res) => {
    req.logout()
    res.redirect('/')
})

สรุป

อย่างที่กล่าวไว้ข้างต้น บทความนี้แนะนำทำระบบ Authentication แบบพื้นฐานด้วยมอดูล Passport-local เพื่อที่จะทำให้เข้าใจหลักการตรวจสอบ Username และ Password อย่างง่ายของมอดูล Passport โดยเราจะใส่ Username และ Password เอาไว้ในสคริต์เลย

ซึ่งหากนำไปใช้งานจริงแนะนำว่าควรนำข้อมูล User เก็บไว้ในฐานข้อมูลจะทำให้ User จะใช้งานระบบได้มากกว่า 1 คนและเพื่อเพิ่มความปลอดภัยของระบบสมาชิกได้

และเราสามารถหาข้อมูลเพิ่มเติมของมอดูล passport ได้จาก https://www.npmjs.com/package/passport

SurveyJS custom survey software

Build Your Own Forms without Manual Coding

SurveyJS UI libraries let you build a JSON-based form management system that integrates with any backend, giving you full control over your data with no user limits. Includes support for custom question types, skip logic, an integrated CSS editor, PDF export, real-time analytics, and more.

Learn more

Top comments (0)

Postgres on Neon - Get the Free Plan

No credit card required. The database you love, on a serverless platform designed to help you build faster.

Get Postgres on Neon