ข้ามไปยังเนื้อหา

HTTPS และ Secure Context

Service worker และ API อื่นๆ ของ PWA ทำงานเฉพาะในสิ่งที่ browser เรียกว่า secure context การทำความเข้าใจว่า secure context คืออะไร ทำไมจึงสำคัญ และจะตรวจสอบได้อย่างไร จะช่วยให้คุณหลีกเลี่ยงปัญหาที่น่าหงุดหงิดในระหว่างการพัฒนาและ deployment

Secure context คือ environment ที่ตรงตามมาตรฐานขั้นต่ำของการรับรองความถูกต้องและความลับ ตามที่กำหนดโดย W3C ในทางปฏิบัติ หน้าจะอยู่ใน secure context เมื่อ:

  • ถูก serve ผ่าน HTTPS (เช่น https://example.com)
  • หรือทำงานบน localhost หรือ 127.0.0.1 (ข้อยกเว้นพิเศษสำหรับการพัฒนา)

หน้าที่ถูก serve ผ่าน http:// ในทุกโดเมนอื่นนอกจาก localhost ไม่ใช่ secure context ไม่ว่าจะ deploy ที่ไหน

Service worker เป็น proxy ที่ทรงพลัง สามารถ intercept ทุก request จากแอปของคุณ แก้ไข response และ cache เนื้อหาได้ หากถูก serve ผ่าน HTTP ทั่วไป ผู้โจมตีที่อยู่บนเครือข่ายเดียวกัน (man-in-the-middle) สามารถ:

  • แทนที่ script ของ service worker ด้วยโค้ดที่เป็นอันตรายได้
  • Intercept หรือดัดแปลง response ที่ service worker cache ไว้
  • ดักจับข้อมูลส่วนตัวก่อนที่จะถูกส่ง

การกำหนดให้ต้อง HTTPS จะทำให้แน่ใจว่า service worker ที่ browser รัน เป็นของจริงและไม่ถูกดัดแปลง

Browser เปิดเผย flag boolean ที่คุณสามารถตรวจสอบได้ตลอดเวลา:

if (window.isSecureContext) {
console.log('Running in a secure context — service worker APIs available.');
} else {
console.warn('Not a secure context. PWA features will be unavailable.');
}

ตรวจสอบ flag นี้ก่อนที่จะพยายาม register service worker หรือใช้ API อื่นๆ ที่ต้องการ secure context (Push, Notifications, Web Authentication, Web Crypto) เพื่อให้ message error ที่ชัดเจนแก่ผู้ใช้แทนที่จะเห็น exception ที่ไม่ได้จัดการ

แม้ว่า origin หลักของคุณจะเป็น HTTPS แต่ browser จะบล็อก mixed content — resource ที่โหลดผ่าน HTTP จากหน้า HTTPS

  • Active mixed content (scripts, stylesheets, iframes) ถูกบล็อกโดยค่าเริ่มต้นในทุก browser สมัยใหม่
  • Passive mixed content (images, audio, video) อาจถูกบล็อกหรือแสดง warning เช่นกัน ขึ้นอยู่กับการตั้งค่า browser

หากหน้า HTTPS ของคุณโหลด resource ผ่าน http:// การ register service worker อาจยังคงทำงานได้ แต่ resource เหล่านั้นจะถูกบล็อกหรือทำให้ lock indicator ใน address bar เสียหาย ตรวจสอบ DevTools Console และ Network tab เพื่อค้นหาคำเตือน mixed content

Service worker ควบคุม URL ภายใน scope ของตัวเอง ซึ่งค่าเริ่มต้นคือ directory ที่ script ของ SW อยู่ Scope นี้ถูกจำกัดโดย HTTPS อีกชั้น:

  • SW ที่ serve จาก https://example.com/app/sw.js ควบคุมเฉพาะ URL ภายใต้ /app/
  • SW ไม่สามารถยกระดับ scope ของตัวเองให้สูงกว่า path ของไฟล์ SW ได้ ยกเว้นจะมี Service-Worker-Allowed response header
  • ใน HTTPS ทั้งหมดนี้ถูก enforce อย่างเคร่งครัด — ไม่มี loophole ใดที่จะอนุญาตให้ SW ที่ไม่น่าเชื่อถือ intercept traffic ที่ไม่ได้ตั้งใจให้ SW ตัวนั้นเข้าถึง

localhost และ 127.0.0.1 ได้รับการยกเว้นโดยทั้ง spec และ browser ว่าเป็น secure context แม้ว่าจะ serve ผ่าน http:// ก็ตาม เหตุผลคือ traffic บน localhost ไม่เคยผ่านเครือข่าย ดังนั้นความเสี่ยงจาก man-in-the-middle จึงไม่มี

ในทางปฏิบัติ:

  • server dev ท้องถิ่นของคุณบน http://localhost:5173 เป็น secure context ที่สมบูรณ์
  • Service worker, Push API และ Web Authentication ทั้งหมดทำงานได้บน localhost โดยไม่ต้องมี TLS certificate
  • เมื่อ deploy เป็น production ต้องใช้ HTTPS จริง — ข้อยกเว้น localhost ไม่ครอบคลุม IP หรือ hostname อื่น
// Safe registration pattern — checks secure context first
async function registerServiceWorker() {
if (!window.isSecureContext) {
console.warn('Secure context required. Skipping service worker registration.');
return;
}
if (!('serviceWorker' in navigator)) {
console.warn('Service workers not supported in this browser.');
return;
}
try {
const reg = await navigator.serviceWorker.register('/sw.js');
console.log('SW registered. Scope:', reg.scope);
} catch (err) {
console.error('SW registration failed:', err);
}
}
registerServiceWorker();
ตัวเลือกBenefitCost
บังคับ HTTPS ทุก origin (รวม subdomain)service worker และ API สมัยใหม่ทำงานได้เต็มรูปแบบ ปลอดภัยจาก MITMต้องจัดการ TLS cert และ redirect ให้ครบทุก environment รวม staging
อนุญาต localhost แบบ HTTP สำหรับ devพัฒนาและทดสอบได้เร็วโดยไม่ต้องตั้ง cert localต้องระวังไม่ให้ config นี้หลุดไปที่ production โดยไม่ตั้งใจ
  • ลืมว่า mixed content (โหลด asset ผ่าน http:// บนหน้า https://) ทำให้ browser บล็อก request นั้นเงียบๆ
  • ตั้ง redirect จาก HTTP ไป HTTPS ที่ระดับ app แทนที่จะทำที่ edge/CDN ทำให้ยังมี window ที่ request แรกไม่ปลอดภัย
  • ไม่ต่ออายุ TLS certificate ทันเวลา ทำให้ service worker ที่เคยลงทะเบียนไว้ใช้งานไม่ได้ทันทีที่ cert หมดอายุ

💡 ตัวอย่างจากของจริง

Google Chrome — ตั้งแต่ปี 2018 เริ่มขึ้น label “Not Secure” ให้ทุกเว็บที่ไม่ใช่ HTTPS บังคับให้ทั้งอุตสาหกรรมย้ายมาใช้ TLS

Let’s Encrypt — ให้ TLS certificate ฟรีอัตโนมัติ ทำให้ต้นทุนของการทำ HTTPS ทุก origin ลดลงจนแทบไม่มีข้อแก้ตัวที่จะไม่ทำ

property ใดบอกคุณว่าหน้าเว็บปัจจุบันรันอยู่ใน secure context หรือไม่?
origin ใดต่อไปนี้ที่ browser สมัยใหม่ถือว่าเป็น secure context?
service worker ลงทะเบียนที่ /dashboard/sw.js โดยไม่มี option หรือ header พิเศษ จะควบคุมหน้าใดบ้าง?
จะทำให้ service worker ที่ลงทะเบียนที่ /app/sw.js มี scope เป็น / (ทั้ง origin) ได้อย่างไร?