Node.js : ระบบ Authentication แบบพื้นฐานด้วยมอดูล Passport-local
Bhurisub Dejpipatpracha
Posted on October 19, 2019
บทความนี้จะขอแนะนำการเขียนสคริปต์ 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
Posted on October 19, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.