HTTPS และ Secure Context
HTTPS และ Secure Context
หัวข้อที่มีชื่อว่า “HTTPS และ Secure Context”Service worker และ API อื่นๆ ของ PWA ทำงานเฉพาะในสิ่งที่ browser เรียกว่า secure context การทำความเข้าใจว่า secure context คืออะไร ทำไมจึงสำคัญ และจะตรวจสอบได้อย่างไร จะช่วยให้คุณหลีกเลี่ยงปัญหาที่น่าหงุดหงิดในระหว่างการพัฒนาและ deployment
Secure context คืออะไร
หัวข้อที่มีชื่อว่า “Secure context คืออะไร”Secure context คือ Window หรือ Worker ที่ origin ถูกส่งมาผ่าน secure transport Browser เปิด boolean ให้ตรวจสอบได้ตลอดเวลา:
console.log(window.isSecureContext); // true or falseBrowser จะตั้ง window.isSecureContext เป็น true เมื่อ:
- หน้าถูกโหลดผ่าน
https://พร้อม TLS certificate ที่ valid - หน้าถูกโหลดจาก
http://localhost,http://127.0.0.1หรือhttp://[::1]— loopback address เหล่านี้ได้รับการยกเว้นโดย spec โดยตรง และ browser สมัยใหม่ทุกตัวถือว่าปลอดภัย
สำหรับ origin http:// อื่นใด window.isSecureContext จะเป็น false และการ register service worker จะ throw SecurityError หรือล้มเหลวแบบเงียบๆ
ทำไม service worker จึงต้องการ secure context
หัวข้อที่มีชื่อว่า “ทำไม service worker จึงต้องการ secure context”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 รัน เป็นของจริงและไม่ถูกดัดแปลง
// Always guard registration with a secure-context checkif ('serviceWorker' in navigator) { if (!window.isSecureContext) { console.warn('Not a secure context — service worker will not register.'); } else { navigator.serviceWorker .register('/sw.js') .then((reg) => console.log('Registered, scope:', reg.scope)) .catch((err) => console.error('Registration failed:', err)); }}Mixed content blocking
หัวข้อที่มีชื่อว่า “Mixed content blocking”หน้าจะถือว่าปลอดภัยก็ต่อเมื่อทุก resource ที่โหลดมาจาก secure origin เท่านั้น การโหลด http:// subresource แม้เพียงตัวเดียวจากหน้า https:// จะสร้าง mixed content ซึ่ง browser จะบล็อกหรือลดระดับ
Mixed content มีผลกับ PWA ในสองทางที่สำคัญ:
- Active mixed content (script, service worker, iframe ผ่าน
http://) ถูกบล็อกเสมอsw.jsของคุณเองต้อง serve ผ่านhttps://เท่านั้น - Passive mixed content (image, audio, video ผ่าน
http://) จะขึ้น warning และในบาง config อาจบังคับให้window.isSecureContextเป็นfalseจนทำให้ register SW ไม่ได้
วิธีแก้ตรงไปตรงมา: ตรวจสอบ URL ของ resource ทุกตัวในแอป ย้ายทั้งหมดไปที่ https:// และใช้ Content Security Policy header เพื่อบังคับต่อไป หากหน้า HTTPS ของคุณโหลด resource ผ่าน http:// การ register service worker อาจยังคงทำงานได้ แต่ resource เหล่านั้นจะถูกบล็อกหรือทำให้ lock indicator ใน address bar เสียหาย ตรวจสอบ DevTools Console และ Network tab เพื่อค้นหาคำเตือน mixed content
กฎ scope ของ service worker
หัวข้อที่มีชื่อว่า “กฎ scope ของ service worker”Scope ของ service worker กำหนดว่ามันควบคุมหน้าใดบ้าง ค่าเริ่มต้นคือ directory ที่ไฟล์ SW อยู่:
| SW file path | Scope เริ่มต้น | ควบคุม |
|---|---|---|
/sw.js | / | ทั้ง origin |
/app/sw.js | /app/ | เฉพาะ /app/ และด้านล่าง |
/shop/checkout/sw.js | /shop/checkout/ | เฉพาะ /shop/checkout/ และด้านล่าง |
คุณสามารถทำให้ scope แคบลงได้โดยส่ง option scope ให้ register() แต่จะขยายให้กว้างกว่า directory ของไฟล์ SW ไม่ได้ — เว้นแต่ server จะส่ง response header Service-Worker-Allowed บนไฟล์ SW พร้อม scope ที่ต้องการ:
Service-Worker-Allowed: /// Widen the scope with the header above set on /app/sw.jsnavigator.serviceWorker.register('/app/sw.js', { scope: '/' });หากไม่มี header นั้น การพยายาม register scope ที่กว้างกว่า directory ของไฟล์ SW จะ throw SecurityError ทั้งหมดนี้ถูก enforce อย่างเคร่งครัดภายใต้ HTTPS — ไม่มี loophole ใดที่จะอนุญาตให้ SW ที่ไม่น่าเชื่อถือ intercept traffic ที่ไม่ได้ตั้งใจให้ SW ตัวนั้นเข้าถึง
ข้อยกเว้น localhost
หัวข้อที่มีชื่อว่า “ข้อยกเว้น localhost”ระหว่างพัฒนาคุณไม่จำเป็นต้องมี self-signed certificate หรือ tunnel ใดๆ browser สมัยใหม่ทุกตัวถือว่า localhost, 127.0.0.1 และ ::1 เป็น secure origin เพราะ traffic บน loopback ไม่เคยผ่านเครือข่ายจริง จึงไม่มีความเสี่ยงจาก man-in-the-middle คุณจึง register service worker, ใช้ Push API, เข้าถึงกล้อง และทดสอบ installability flow ทั้งหมดได้บน http://localhost เดฟเซิร์ฟเวอร์ธรรมดา
// Full secure-context diagnostic you can drop into DevTools(function diagnose() { const results = { isSecureContext: window.isSecureContext, protocol: location.protocol, hostname: location.hostname, serviceWorkerSupported: 'serviceWorker' in navigator, }; console.table(results); if (!results.isSecureContext) { console.warn( 'Secure context required. Deploy over HTTPS or use localhost.' ); }})();// Safe registration pattern — checks secure context firstasync 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();ข้อแลกเปลี่ยน
หัวข้อที่มีชื่อว่า “ข้อแลกเปลี่ยน”| ตัวเลือก | Benefit | Cost |
|---|---|---|
| บังคับ 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 หมดอายุ
Chrome เริ่มติด label “Not Secure” ให้ทุกหน้าที่เป็น HTTP ธรรมดาตั้งแต่ปี 2018 ผลักดันให้อุตสาหกรรมส่วนใหญ่ย้ายไปใช้ TLS (Chromium Blog, “A secure web is here to stay,” ก.พ. 2018) ส่วน TLS certificate ฟรีแบบอัตโนมัติจาก Let’s Encrypt ก็ตัดข้อแก้ตัวเรื่องต้นทุนที่เหลืออยู่ของการทำ HTTPS ทุก origin ไปเกือบหมด