รูปแบบการยืนยันตัวตนที่ปลอดภัย
การจัดเก็บโทเค็น (หน่วยความจำเทียบกับ localStorage เทียบกับคุกกี้ httpOnly) การรีเฟรชแบบเงียบ และการออกจากระบบเมื่อปิดแท็บ
รูปแบบการยืนยันตัวตนที่ปลอดภัย เป็นบทเรียน Vue Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Vue Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Vue Academy มีบทเรียนทั้งหมด 4 บทเรียน
โทเค็นและตำแหน่งจัดเก็บ
SPA ใช้โทเค็นเพื่อยืนยันตัวตน แต่ตำแหน่งที่จัดเก็บโทเค็นจะเป็นตัวกำหนดความเสี่ยงจาก XSS และ CSRF รูปแบบสมัยใหม่จะแยกโทเค็นเข้าถึงอายุสั้นออกจากโทเค็นรีเฟรชอายุยาว และจัดเก็บแต่ละโทเค็นไว้ต่างกัน
ปัญหาของ localStorage
การจัดเก็บโทเค็นใน localStorage สะดวกแต่มีอันตราย เพราะสคริปต์ใด ๆ ที่ถูกแทรกด้วย XSS สามารถอ่านและส่งโทเค็นออกไปได้ หลีกเลี่ยงการเก็บข้อมูลรับรองไว้ที่นั่น
// AVOID
localStorage.setItem("token", accessToken);โทเค็นเข้าถึงในหน่วยความจำ
เก็บโทเค็นเข้าถึงไว้ในตัวแปร JavaScript หรือรีแอกทีฟรีฟ โทเค็นจะหายไปเมื่อโหลดใหม่ ดังนั้น XSS ที่ทำงานสำเร็จจะมีช่วงเวลาโจมตีสั้นลงมาก และจะไม่มีข้อมูลใดคงอยู่บนดิสก์
import { ref } from "vue";
export const accessToken = ref(null);โทเค็นรีเฟรชในคุกกี้ httpOnly
โทเค็นรีเฟรชจะอยู่ในคุกกี้ HttpOnly, Secure, SameSite JavaScript ไม่สามารถอ่านคุกกี้นี้ได้ ดังนั้น XSS จึงขโมยไม่ได้ และเบราว์เซอร์จะส่งคุกกี้นี้เฉพาะไปยังจุดปลายทางการยืนยันตัวตนของคุณ
Set-Cookie: refresh=...; HttpOnly; Secure; SameSite=Strict; Path=/authการแนบโทเค็นเข้าถึง
ตัวสกัดกั้นคำขอของ Axios จะเพิ่มโทเค็นเข้าถึงในหน่วยความจำลงในส่วนหัวการอนุญาตของทุกคำเรียก
api.interceptors.request.use((config) => {
if (accessToken.value) {
config.headers.Authorization = "Bearer " + accessToken.value;
}
return config;
});การตรวจจับการหมดอายุ: 401
เมื่อโทเค็นเข้าถึงหมดอายุ เซิร์ฟเวอร์จะตอบกลับด้วย 401 Unauthorized ตัวสกัดกั้นการตอบกลับจะตรวจจับเหตุการณ์นี้เพื่อเรียกการรีเฟรช
api.interceptors.response.use(
(res) => res,
async (error) => {
if (error.response?.status === 401) {
// attempt refresh
}
return Promise.reject(error);
}
);การรีเฟรชโทเค็น
เมื่อได้รับ 401 ให้เรียกจุดปลายทางสำหรับรีเฟรช เบราว์เซอร์จะส่งคุกกี้รีเฟรช httpOnly ให้อัตโนมัติ (withCredentials) และเซิร์ฟเวอร์จะส่งโทเค็นเข้าถึงใหม่กลับมา
const { data } = await axios.post("/auth/refresh", null, {
withCredentials: true
});
accessToken.value = data.accessToken;การลองส่งคำขอเดิมอีกครั้ง
หลังรีเฟรช ให้ส่งคำขอเดิมที่ล้มเหลวซ้ำด้วยโทเค็นใหม่ เพื่อไม่ให้ผู้ใช้สังเกตเห็น
async (error) => {
const original = error.config;
if (error.response?.status === 401 && !original._retry) {
original._retry = true;
const { data } = await axios.post("/auth/refresh", null, { withCredentials: true });
accessToken.value = data.accessToken;
original.headers.Authorization = "Bearer " + data.accessToken;
return api(original);
}
return Promise.reject(error);
}ป้องกันการรีเฟรชถล่มพร้อมกัน
หากคำขอจำนวนมากได้รับ 401 พร้อมกัน ให้เข้าคิวไว้เบื้องหลังการรีเฟรชเดียวที่กำลังทำงานอยู่ เพื่อไม่ให้เรียกปลายทางรีเฟรชซ้ำ ๆ
let refreshing = null;
function refresh() {
if (!refreshing) {
refreshing = axios.post("/auth/refresh", null, { withCredentials: true })
.finally(() => { refreshing = null; });
}
return refreshing;
}การออกจากระบบ
เมื่อออกจากระบบ ให้ล้างโทเค็นในหน่วยความจำและเรียกปลายทางที่ล้างคุกกี้รีเฟรชจากฝั่งเซิร์ฟเวอร์
async function logout() {
accessToken.value = null;
await axios.post("/auth/logout", null, { withCredentials: true });
}ผสานกับการป้องกัน CSRF
เนื่องจากคุกกี้รีเฟรชถูกส่งโดยอัตโนมัติ ให้ป้องกันปลายทางดังกล่าวด้วย SameSite และโทเค็น CSRF เช่นเดียวกับเส้นทางอื่น ๆ ที่ยืนยันตัวตนด้วยคุกกี้
ตรวจสอบอย่างรวดเร็ว
ควรเก็บ access token และ refresh token ไว้ที่ใดบ้าง
สรุป
เก็บ access token ไว้ในรีฟที่อยู่ในหน่วยความจำ (ห้ามใช้ localStorage) และเก็บ refresh token ไว้ในคุกกี้ HttpOnly ตัวดักจับคำขอจะเพิ่มโทเค็นแบบผู้ถือ ส่วนตัวดักจับการตอบกลับจะตรวจจับ 401 เรียกปลายทางรีเฟรช อัปเดตโทเค็น และลองส่งคำขอเดิมอีกครั้ง โดยรวมการรีเฟรชที่เกิดพร้อมกันให้เหลือครั้งเดียวและใช้ควบคู่กับการป้องกัน CSRF
คำถามที่พบบ่อย
บทเรียน “รูปแบบการยืนยันตัวตนที่ปลอดภัย” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “รูปแบบการยืนยันตัวตนที่ปลอดภัย” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Vue Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Vue Academy มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “รูปแบบการยืนยันตัวตนที่ปลอดภัย”
การจัดเก็บโทเค็น (หน่วยความจำเทียบกับ localStorage เทียบกับคุกกี้ httpOnly) การรีเฟรชแบบเงียบ และการออกจากระบบเมื่อปิดแท็บ คุณปฏิบัติ Vue Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Vue Academy หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Vue Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “รูปแบบการยืนยันตัวตนที่ปลอดภัย” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Vue Academy นี้ได้ไหม
ได้ บทเรียน Vue Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การป้องกัน XSS ใน Vue
- Content Security Policy (CSP) กับ Vue
- การป้องกัน CSRF ใน SPA ของ Vue
- รูปแบบการยืนยันตัวตนที่ปลอดภัย