เจาะลึก JWT คืออะไร? อธิบายวิธีทำระบบล็อกอินแบบเข้าใจง่ายสำหรับมือใหม่

7 นาที 8 views บันทึกเป็น PDF
เจาะลึก JWT คืออะไร? อธิบายวิธีทำระบบล็อกอินแบบเข้าใจง่ายสำหรับมือใหม่

อยากทำระบบล็อกอินแต่สับสนเรื่อง JWT? มาเรียนรู้พื้นฐาน JSON Web Token พร้อมวิธีเขียนโค้ดด้วย Node.js และ Express แบบเข้าใจง่าย ไม่ต้องปวดหัวกับ Session อีกต่อไป

JWT คืออะไร ทำไมต้องรู้จัก

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

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

ถ้าคุณกำลังฝึกเขียนเว็บ การเข้าใจ JWT จะช่วยให้คุณทำระบบล็อกอินได้โดยไม่ต้องปวดหัวกับการเก็บสถานะของเซิร์ฟเวอร์ (Session) ให้วุ่นวาย มันเป็นวิธีที่นิยมมากในการทำระบบ API (ช่องทางสื่อสารระหว่างซอฟต์แวร์) สมัยใหม่ เพราะมันเบาและจัดการได้ง่ายครับ

โครงสร้างของ JWT ที่ควรรู้

JWT เป็นเพียงข้อความยาวๆ ที่แบ่งเป็น 3 ส่วนด้วยจุด (dot) ซึ่งทั้งสามส่วนนี้รวมกันเป็นสตริง (ข้อความตัวอักษร) เส้นเดียว ส่วนประกอบประกอบด้วย Header (ส่วนหัว), Payload (เนื้อหา), และ Signature (ลายเซ็นยืนยัน)

Header จะบอกว่าใช้การเข้ารหัสแบบไหน ส่วน Payload คือจุดที่เก็บข้อมูลผู้ใช้ เช่น ID (รหัสประจำตัว) หรือเวลาหมดอายุ ส่วนสุดท้ายคือ Signature ซึ่งสำคัญที่สุดเพราะมันใช้กุญแจลับ (Secret Key) สร้างขึ้นมาเพื่อป้องกันไม่ให้ใครแอบแก้ไขข้อมูลข้างใน

จำไว้ว่า JWT ไม่ได้ถูก Encryption (การทำให้ข้อมูลอ่านไม่ออก) แต่เป็นเพียงการลงลายเซ็น ถ้ามีใครแอบแก้ไขข้อมูลใน Payload ลายเซ็นเดิมจะใช้ไม่ได้ทันที ทำให้เซิร์ฟเวอร์รู้ได้ทันทีว่าโทเค็นนี้ถูกดัดแปลงมาครับ

ขั้นตอนการทำงานของ JWT

  1. ผู้ใช้กรอกชื่อผู้ใช้และรหัสผ่านเพื่อล็อกอินผ่านหน้าเว็บ
  2. เซิร์ฟเวอร์ตรวจสอบความถูกต้อง ถ้าผ่านจะสร้าง JWT ขึ้นมาแล้วส่งกลับไปให้ผู้ใช้
  3. ผู้ใช้เก็บ JWT ไว้ในเครื่อง และแนบไปกับทุกคำขอ (Request) ที่ส่งไปยังเซิร์ฟเวอร์ในหัวข้อ Authorization
  4. เซิร์ฟเวอร์รับคำขอมาตรวจสอบลายเซ็น ถ้าถูกต้องก็อนุญาตให้เข้าถึงข้อมูลได้ทันที

ขั้นตอนเหล่านี้ทำให้เซิร์ฟเวอร์เป็นแบบ Stateless (ไม่ต้องจำสถานะการล็อกอินไว้ที่ฝั่งเซิร์ฟเวอร์) ซึ่งช่วยลดภาระของระบบลงได้อย่างมหาศาล เพราะเซิร์ฟเวอร์แค่เช็กว่า "ลายเซ็นนี้จริงไหม" เท่านั้น

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

สร้างระบบล็อกอินด้วย Node.js

เรามาลองเขียนโค้ดง่ายๆ ด้วย express (เฟรมเวิร์กสำหรับสร้างเว็บด้วย Node.js) และไลบรารี jsonwebtoken กันครับ สิ่งแรกที่ต้องทำคือติดตั้งโปรแกรมผ่านคำสั่ง npm install express jsonwebtoken

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
app.use(express.json());

const SECRET = 'my-secret-key'; // กุญแจลับสำหรับเซ็นชื่อ

// จำลองข้อมูลผู้ใช้
const users = [{ id: 1, username: 'alice', password: '123' }];

app.post('/login', (req, res) => {
  const { username, password } = req.body;
  const user = users.find(u => u.username === username && u.password === password);
  if (!user) return res.status(401).send('ล็อกอินไม่ผ่าน');
  
  // สร้างโทเค็นโดยใช้ ID ผู้ใช้และกุญแจลับ
  const token = jwt.sign({ userId: user.id }, SECRET, { expiresIn: '1h' });
  res.json({ token });
});

ในโค้ดนี้ เราสร้างเส้นทาง /login เพื่อเช็กชื่อและรหัสผ่าน หากตรงกันเราจะใช้ฟังก์ชัน jwt.sign สร้างโทเค็นที่มีอายุการใช้งาน 1 ชั่วโมง ผลลัพธ์ที่ได้จะเป็นข้อความยาวๆ ที่เรียกว่า JWT ส่งกลับไปให้ฝั่งผู้ใช้เก็บไว้

ผลลัพธ์เมื่อคุณส่งข้อมูล JSON ไปที่ /login คุณจะได้รับข้อความตอบกลับในรูปแบบ {"token": "eyJhbGci..."} ซึ่งนี่คือบัตรผ่านที่คุณต้องนำไปใช้ในคำขอถัดไปครับ

การดึงข้อมูลโดยใช้โทเค็น

เมื่อผู้ใช้มีโทเค็นแล้ว เวลาจะขอข้อมูลส่วนตัว (เช่น หน้าโปรไฟล์) ก็ต้องส่งโทเค็นนี้ไปใน Header ที่ชื่อว่า Authorization เพื่อให้เซิร์ฟเวอร์ตรวจสอบก่อนอนุญาตให้เข้าดูข้อมูลได้

app.get('/profile', (req, res) => {
  const authHeader = req.headers.authorization;
  if (!authHeader) return res.status(401).send('ไม่มีโทเค็น');
  
  const token = authHeader.split(' ')[1]; // ดึงเฉพาะส่วนที่เป็นโทเค็น
  try {
    const payload = jwt.verify(token, SECRET); // ตรวจสอบความถูกต้อง
    res.send(`สวัสดีผู้ใช้รหัส: ${payload.userId}`);
  } catch (err) {
    res.status(401).send('โทเค็นไม่ถูกต้องหรือหมดอายุ');
  }
});

เราใช้ jwt.verify เพื่อตรวจสอบว่าโทเค็นนี้เป็นของจริงหรือไม่ ถ้าตัวเลขใน Payload ถูกแก้ไข ลายเซ็นจะไม่ตรงและโปรแกรมจะโยน Error ออกมาทันที ทำให้เรามั่นใจได้ว่าข้อมูลที่ได้มานั้นปลอดภัยครับ

ผลลัพธ์ที่ได้จากการเรียก API นี้ หากส่งโทเค็นที่ถูกต้องไป คุณจะได้รับข้อความ สวัสดีผู้ใช้รหัส: 1 กลับมา หากโทเค็นหมดอายุหรือปลอมแปลงมา ระบบจะแจ้งเตือนว่าไม่สามารถเข้าถึงได้ทันที

จุดที่มือใหม่มักพลาด

ข้อผิดพลาดแรกคือการเก็บ SECRET ไว้ในฝั่ง Client (หน้าเว็บ) ซึ่งห้ามทำเด็ดขาด เพราะถ้าคนอื่นรู้กุญแจนี้ เขาจะปลอมแปลงโทเค็นได้ทั้งหมด ให้เก็บไว้ในไฟล์ .env (ไฟล์เก็บค่าความลับของโปรเจกต์) เท่านั้น

ข้อสองคือการลืมตรวจสอบเวลาหมดอายุ หรือใส่ข้อมูลสำคัญอย่างรหัสผ่านลงใน Payload อย่าลืมว่าใครๆ ก็สามารถถอดรหัส Payload ออกมาดูได้ ดังนั้นให้ใส่แค่ ID หรือสิทธิ์การเข้าถึง (Role) ก็พอครับ

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

สรุป: เริ่มต้นใช้งานจริง

JWT ไม่ใช่เรื่องเวทมนตร์ แต่มันเป็นแค่การเซ็นชื่อกำกับข้อมูลเพื่อให้เซิร์ฟเวอร์เชื่อถือได้โดยไม่ต้องจำสถานะ เมื่อคุณเข้าใจว่ามันประกอบด้วยสามส่วนและทำงานผ่านลายเซ็น คุณก็สามารถนำไปประยุกต์ใช้ในโปรเจกต์ต่างๆ ได้ทันที

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

หัวใจสำคัญคือการทดสอบ แนะนำให้โหลดโปรแกรมชื่อ Postman มาลองยิง API ของคุณเองดู คุณจะเห็นภาพชัดเจนว่า Header ของ HTTP ทำงานอย่างไร และโทเค็นที่ส่งไปนั้นหน้าตาเป็นแบบไหน ขอให้สนุกกับการเขียนโค้ดครับ!


ที่มา: JWT Auth Without the Confusion — DEV Community

แชร์บทความ

Facebook X LINE

บทความที่เกี่ยวข้อง

จัดการเซิร์ฟเวอร์ผ่าน VS Code ให้ง่ายขึ้นด้วย Easy SSH พร้อมฟีเจอร์โหลดไฟล์ผ่านคลิกเดียว

จัดการเซิร์ฟเวอร์ผ่าน VS Code ให้ง่ายขึ้นด้วย Easy SSH พร้อมฟีเจอร์โหลดไฟล์ผ่านคลิกเดียว

เบื่อไหมที่ต้องสลับหน้าจอไปมาเพื่อจัดการเซิร์ฟเวอร์? มาลองใช้ Easy SSH ปลั๊กอิน VS Code ที่ช่วยให้คุณรีโมทผ่าน Terminal ได้สะดวก แถมโหลดไฟล์ได้ง่ายแค่กด Ctrl+click

ที่มา: DEV Community

1 hour ago 11 นาที
2 views
วิธีดึงข้อมูลราคาจาก Google Hotels ด้วย API สำหรับนักพัฒนา

วิธีดึงข้อมูลราคาจาก Google Hotels ด้วย API สำหรับนักพัฒนา

อยากทำแอปท่องเที่ยวแต่ดึงข้อมูลราคาจาก Google Hotels ไม่ได้? มาดูวิธีใช้ Apify Actor ช่วยดึงข้อมูลแบบอัตโนมัติด้วย Python ง่ายๆ ไม่ต้องกลัวเว็บพัง

ที่มา: DEV Community

5 hours ago 8 นาที
3 views
วิธีเช็กความพร้อมโปรเจกต์ก่อนปล่อยงานจริงด้วย ReleaseReady

วิธีเช็กความพร้อมโปรเจกต์ก่อนปล่อยงานจริงด้วย ReleaseReady

เคยไหม? โค้ดรันได้ในเครื่องแต่พอปล่อยจริงกลับพัง! มาดูวิธีตรวจสอบความพร้อมของโปรเจกต์ก่อนอัปขึ้น GitHub ด้วยเครื่องมือ ReleaseReady กัน

ที่มา: DEV Community

9 hours ago 9 นาที
4 views