Session Token คือตัวระบุเฉพาะที่เซิร์ฟเวอร์สร้างขึ้นหลังจากผู้ใช้ยืนยันตัวตนสำเร็จและใช้เพื่อระบุคำขอที่ตามมา แตกต่างจากโทเค็นแบบพึ่งพาตนเองได้ (JWT) ตรงที่ session token เป็นสตริงสุ่มที่ไม่มีข้อมูลในตัวเอง: ข้อมูลเซสชันทั้งหมดจะถูกจัดเก็บไว้บนเซิร์ฟเวอร์ใน RAM หรือฐานข้อมูล ตามข้อมูลจาก OAuth.com, 2025 session token ยังคงเป็นกลไกการยืนยันตัวตนที่พบมากที่สุดในแอปพลิเคชันเว็บฝั่งเซิร์ฟเวอร์และสถาปัตยกรรมมือถือแบบไฮบริด
ประเด็นสำคัญ
Session Token (ตัวระบุเซสชัน) คือสตริงเฉพาะที่เซิร์ฟเวอร์สร้างและเชื่อมโยงกับข้อมูลเซสชันหลังจากการยืนยันตัวตนของผู้ใช้ โทเค็นไม่มีข้อมูลใด ๆ เกี่ยวกับผู้ใช้ — มันเป็นเพียงกุญแจสู่ข้อมูลที่จัดเก็บบนเซิร์ฟเวอร์ วิธีการนี้เรียกว่า การยืนยันตัวตนแบบ stateful: เซิร์ฟเวอร์จัดเก็บสถานะของแต่ละเซสชันที่ทำงานอยู่และตรวจสอบทุกครั้งที่มีคำขอ
ข้อมูลเซสชันประกอบด้วย: ID ผู้ใช้ เวลาเข้าสู่ระบบ ที่อยู่ IP user-agent รายการสิทธิ์ เวลากิจกรรมล่าสุด เมื่อไคลเอ็นต์ส่งคำขอพร้อม session token เซิร์ฟเวอร์จะค้นหาบันทึกที่เกี่ยวข้องในที่เก็บเซสชัน ตรวจสอบความถูกต้อง และดึงข้อมูลเพื่อประมวลผลคำขอ หากบันทึกเซสชันหายไปหรือหมดอายุ เซิร์ฟเวอร์จะส่งคืนข้อผิดพลาดการยืนยันตัวตนและต้องให้เข้าสู่ระบบอีกครั้ง
ตามข้อมูลของ OWASP, 2025 session token ยังคงเป็นมาตรฐานสำหรับแอปพลิเคชันที่ต้องการการเพิกถอนการเข้าถึงทันที — ตัวอย่างเช่น ในระบบธนาคารและพอร์ทัลองค์กรที่ผู้ดูแลระบบต้องสามารถยุติเซสชันของผู้ใช้ได้ทันที ในระบบเหล่านี้ session token ให้การควบคุมการเข้าถึงอย่างสมบูรณ์ซึ่งไม่สามารถบรรลุได้สำหรับโทเค็นแบบ stateless โดยไม่มีกลไกการบล็อกเพิ่มเติม
กระบวนการเริ่มต้นเมื่อไคลเอ็นต์ส่งข้อมูลประจำตัวไปยังเซิร์ฟเวอร์ยืนยันตัวตน เซิร์ฟเวอร์ตรวจสอบชื่อผู้ใช้และรหัสผ่าน สร้างบันทึกเซสชันในที่เก็บ (โดยปกติคือ Redis หรือฐานข้อมูล) และส่งคืน session token เฉพาะให้กับไคลเอ็นต์ ไคลเอ็นต์บันทึกโทเค็นและส่งไปพร้อมกับคำขอที่ตามมาทุกครั้ง และเซิร์ฟเวอร์จะตรวจสอบการมีอยู่และความถูกต้องของเซสชันทุกครั้ง
Redis เป็นที่เก็บเซสชันที่ได้รับความนิยมมากที่สุดเนื่องจากการจัดเก็บในหน่วยความจำและการรองรับ TTL (อายุการใช้งาน) แต่ละเซสชันจะถูกจัดเก็บเป็นคู่คีย์-ค่า โดยที่คีย์คือ session token และค่าคือวัตถุ JSON ที่มีข้อมูลเซสชัน TTL จะลบเซสชันที่หมดอายุโดยอัตโนมัติ ทางเลือกอื่น: Memcached (หน่วยความจำเท่านั้น ไม่มีการจัดเก็บในดิสก์), PostgreSQL/MySQL (คงทนแต่ช้ากว่า) และ DynamoDB (สำหรับโครงสร้างพื้นฐาน AWS)
ตัวอย่างโครงสร้างเซสชันใน Redis: session:{token} → {“userId”: 42, “role”: “admin”, “createdAt”: 1812345678, “lastAccess”: 1812345678} เซิร์ฟเวอร์อัปเดต lastAccess ทุกครั้งที่มีคำขอ ซึ่งช่วยให้สามารถกำหนดระยะเวลาไม่มีการเคลื่อนไหว — การยุติเซสชันอัตโนมัติหลังจากช่วงเวลาไม่มีการใช้งาน
Session Token สามารถส่งได้สองวิธี: ผ่านคุกกี้ HTTP หรือผ่านส่วนหัว HTTP Authorization คุกกี้เป็นวิธีดั้งเดิมสำหรับแอปพลิเคชันเว็บ: เซิร์ฟเวอร์ตั้งค่าคุกกี้ด้วยแฟล็ก HttpOnly (ไม่สามารถเข้าถึงได้จาก JavaScript), Secure (เฉพาะ HTTPS) และ SameSite (ป้องกัน CSRF) สำหรับแอปพลิเคชันมือถือ มักใช้ส่วนหัว Authorization: Bearer <session_token> มากกว่า เนื่องจากกลไกคุกกี้ไม่สะดวกเสมอไปในไคลเอ็นต์แบบเนทีฟ
วงจรชีวิตของ session token ประกอบด้วยสามขั้นตอน: การสร้าง การรักษาเซสชันที่ทำงานอยู่ และการยุติ แต่ละขั้นตอนต้องมีการกำหนดค่าความปลอดภัยที่เหมาะสมเพื่อป้องกันการรั่วไหลหรือการสกัดกั้นโทเค็น
การสร้าง — เซิร์ฟเวอร์สร้างสตริงสุ่มที่ปลอดภัยด้วยการเข้ารหัสขนาด 128–256 บิต (เช่น ผ่าน SecureRandom ใน Java หรือ os.urandom ใน Python) โทเค็นต้องคาดเดาไม่ได้ — การใช้ UUID หรือการประทับเวลาโดยไม่มีเอนโทรปีไม่เป็นที่ยอมรับ การจัดเก็บ บนไคลเอ็นต์: ใน iOS — Keychain, ใน Android — EncryptedSharedPreferences, ในเว็บ — คุกกี้ HttpOnly การลบเกิดขึ้นเมื่อออกจากระบบ: ไคลเอ็นต์ลบโทเค็นออกจากที่เก็บ เซิร์ฟเวอร์ลบบันทึกเซสชันจาก Redis หลังจากออกจากระบบ session token จะไร้ประโยชน์ — เซิร์ฟเวอร์จะไม่พบบันทึกที่เกี่ยวข้อง
ตามข้อมูลของ SANS Institute, 2025 การยุติเซสชันที่ถูกต้อง (การออกจากระบบด้วยการทำความสะอาดฝั่งเซิร์ฟเวอร์) ป้องกันการโจมตีโดยใช้โทเค็นที่ถูกขโมยได้ถึง 70% สิ่งสำคัญคือไม่เพียงแค่ลบโทเค็นบนไคลเอ็นต์เท่านั้น แต่ยังต้องทำให้เซสชันบนเซิร์ฟเวอร์เป็นโมฆะด้วย
Session Token และ JWT แสดงถึงแนวทางการยืนยันตัวตนที่แตกต่างกันสองแบบ Session Token เป็น stateful (เซิร์ฟเวอร์จัดเก็บสถานะ) JWT เป็น stateless (ข้อมูลภายในโทเค็น) การเลือกระหว่างทั้งสองขึ้นอยู่กับสถาปัตยกรรมแอปพลิเคชันและข้อกำหนดด้านความปลอดภัย
| เกณฑ์ | Session Token | JWT |
|---|---|---|
| โมเดล | Stateful (ข้อมูลบนเซิร์ฟเวอร์) | Stateless (ข้อมูลในโทเค็น) |
| การเพิกถอน | ทันที — ลบเซสชันจาก Redis | ต้องใช้บัญชีดำหรือ TTL สั้น |
| ขนาด | 16–64 ไบต์ | 500–2000 ไบต์ |
| การจัดเก็บข้อมูล | เฉพาะบนเซิร์ฟเวอร์ (ปลอดภัย) | ภายในโทเค็น (base64, ไม่ได้เข้ารหัส) |
| การปรับขนาด | ต้องการพื้นที่จัดเก็บร่วมกัน (Redis) | ไม่จำเป็น — โทเค็นถูกตรวจสอบในเครื่อง |
| การป้องกัน CSRF | ต้องการคุกกี้ SameSite + โทเค็น CSRF | ไม่จำเป็น (โทเค็นในส่วนหัว) |
Session Token เหมาะกว่าเมื่อ: ต้องการการเพิกถอนเซสชันทันที (ธนาคาร, แผงผู้ดูแลระบบ), แอปพลิเคชันทำงานบนเซิร์ฟเวอร์หนึ่งเครื่องหรือหลายเครื่องด้วย Redis ร่วมกัน, ข้อมูลเซสชันมีขนาดใหญ่และไม่พอดีกับ JWT, หรือทีมต้องการลดความเสี่ยงของการรั่วไหลของข้อมูลผ่านการถอดรหัสโทเค็น ในสถานการณ์เหล่านี้ session token ให้การบล็อกการเข้าถึงทันทีเมื่อมีกิจกรรมที่น่าสงสัย — เพียงลบบันทึกหนึ่งรายการจาก Redis เซสชันทั้งหมดของผู้ใช้ก็จะไม่ถูกต้อง
ตามข้อมูลของ Redis, 2025 การใช้ TTL ในระดับคีย์เซสชัน (คำสั่ง EXPIRE) จะล้างเซสชันที่หมดอายุโดยอัตโนมัติโดยไม่มีค่าใช้จ่ายเพิ่มเติมสำหรับงานเบื้องหลัง สำหรับเซสชันที่มี TTL 1 ชั่วโมงและโหลดผู้ใช้พร้อมกัน 10,000 คน Redis ใช้ RAM ประมาณ 1 GB โดยมีขนาดเซสชัน 1 KB ซึ่งทำให้คุ้มค่าสำหรับแอปพลิเคชันส่วนใหญ่
ความปลอดภัยของ session token ขึ้นอยู่กับหลักการสองประการ: โทเค็นต้องคาดเดาไม่ได้และได้รับการป้องกันระหว่างการส่งและจัดเก็บ ภัยคุกคามหลักคือการสกัดกั้นโทเค็น (man-in-the-middle, XSS), การคาดเดาโทเค็น (การสร้างที่อ่อนแอ) และการตรึงเซสชัน (session fixation)
การป้องกันรวมถึง: การใช้ HTTPS สำหรับคำขอทั้งหมดที่มีโทเค็น การตั้งค่า TTL เซสชันสั้น (ไม่มีการเคลื่อนไหว 15–60 นาที), การผูกเซสชันกับ IP และ user-agent (การตรวจสอบเพิ่มเติมในทุกคำขอ), การใช้แฟล็ก Secure และ HttpOnly สำหรับคุกกี้ และการหมุน session_token เป็นระยะหลังจากการดำเนินการที่ละเอียดอ่อน (เปลี่ยนรหัสผ่าน, เพิ่มสิทธิ์) OWASP ยังแนะนำให้ใช้ การจัดการเซสชัน โดยทำให้เซสชันเก่าเป็นโมฆะเมื่อสร้างเซสชันใหม่หลังเข้าสู่ระบบ — ซึ่งป้องกัน session fixation
ตามข้อมูลของ OWASP ASVS, 2025 เซสชันต้องผูกกับอย่างน้อยสองปัจจัย: โทเค็นเอง (สิ่งที่ไคลเอ็นต์มี) และ IP/user-agent (สิ่งที่เซิร์ฟเวอร์รู้) หากปัจจัยเหล่านี้ไม่ตรงกัน เซิร์ฟเวอร์ควรยุติเซสชันและต้องยืนยันตัวตนอีกครั้ง
ด้านล่างเป็นตัวอย่างการใช้งาน session token ฝั่งเซิร์ฟเวอร์ใน Kotlin โดยใช้ Spring Boot และ Redis เซิร์ฟเวอร์สร้างโทเค็นที่ปลอดภัยด้วยการเข้ารหัสผ่าน SecureRandom บันทึกเซสชันใน Redis ด้วย TTL และตรวจสอบทุกครั้งที่มีคำขอ โค้ดสาธิตการดำเนินการหลักสามอย่าง: การสร้างเซสชัน การตรวจสอบความถูกต้อง และการทำให้เป็นโมฆะ
data class Session(
val userId: Long,
val role: String,
val createdAt: Long,
val lastAccess: Long
)
object SessionManager {
private val redis = JedisPool("localhost", 6379)
fun createSession(userId: Long, role: String): String {
val token = generateSecureToken()
val session = Session(userId, role, now(), now())
redis.resource.use { conn ->
conn.setex("session:$token", 3600, toJson(session))
}
return token
}
fun validateSession(token: String): Session? {
redis.resource.use { conn ->
val json = conn.get("session:$token") ?: return null
return fromJson(json)
}
}
fun invalidateSession(token: String) {
redis.resource.use { it.del("session:$token") }
}
private fun generateSecureToken(): String {
val bytes = ByteArray(32)
SecureRandom().nextBytes(bytes)
return Base64.getUrlEncoder().withoutPadding().encodeToString(bytes)
}
}
การใช้งานนี้ใช้ JedisPool สำหรับการเชื่อมต่อที่ปลอดภัยกับ Redis แบบหลายเธรด เมธอด createSession ตั้งค่า TTL เป็น 1 ชั่วโมง (3600 วินาที) — หลังจากช่วงเวลานี้ Redis จะลบบันทึกโดยอัตโนมัติ เมธอด validateSession ส่งคืน null สำหรับเซสชันที่ไม่มีอยู่หรือหมดอายุ ซึ่งช่วยให้เซิร์ฟเวอร์จัดการคำขอที่มีโทเค็นไม่ถูกต้องได้อย่างถูกต้องและส่งคืน HTTP 401
คำถามที่พบบ่อย
Session token คือตัวระบุเซสชันฝั่งเซิร์ฟเวอร์ (stateful) Access token คือข้อมูลประจำตัวสำหรับการเข้าถึง API (อาจเป็น JWT หรือ opaque) โดยทั่วไป Session token ใช้สำหรับเซสชันเว็บ ส่วน access token ใช้สำหรับคำขอ API ในแอปพลิเคชันมือถือและ SPA ทั้งสองสามารถอยู่ร่วมกันได้: session token สำหรับเว็บ, access token สำหรับ API
การป้องกันหลักคือการตั้งค่าแฟล็ก HttpOnly บนคุกกี้ที่มีโทเค็นเซสชัน แฟล็กนี้ป้องกันการเข้าถึงคุกกี้จาก JavaScript ทำให้การโจมตี XSS ไร้ประโยชน์สำหรับการขโมยโทเค็น นอกจากนี้ แฟล็ก SameSite=Strict ป้องกันการส่งคุกกี้กับคำขอข้ามไซต์ ป้องกัน CSRF
แนะนำให้ใช้ระยะเวลาสองแบบ: ระยะเวลาสัมบูรณ์ (8–24 ชั่วโมง — อายุเซสชันสูงสุด) และ ระยะเวลาสัมพัทธ์ (ไม่มีการเคลื่อนไหว 15–30 นาที — หลังจากนั้นเซสชันจะสิ้นสุด) สำหรับแอปพลิเคชันธนาคาร ระยะเวลาสัมบูรณ์จะลดลงเหลือ 1–2 ชั่วโมง; สำหรับไคลเอ็นต์อีเมล อาจถึง 7 วัน
Session fixation คือการโจมตีที่ผู้โจมตีบังคับให้ผู้ใช้ใช้ตัวระบุเซสชันที่รู้จัก การป้องกัน: หลังจากการยืนยันตัวตนสำเร็จ เซิร์ฟเวอร์ต้องสร้าง session token ใหม่ แทนที่จะใช้โทเค็นที่ไคลเอ็นต์ส่งต่อไป โทเค็นเก่าต้องถูกทำให้เป็นโมฆะโดยไม่คำนึงถึงที่มา
ได้ session token เหมาะสำหรับ REST API หากไคลเอ็นต์ส่งในส่วนหัว Authorization (ไม่ใช่คุกกี้) สำหรับแอปพลิเคชันมือถือ นี่เป็นวิธีปฏิบัติทั่วไป ข้อเสีย: เมื่อปรับขนาดเป็นหลายเซิร์ฟเวอร์ จำเป็นต้องมีที่เก็บเซสชันร่วมกัน (Redis) ซึ่งเพิ่มจุดเดียวที่ทำให้เกิดความล้มเหลวในสถาปัตยกรรม
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม