TL; DR
JSONP เป็นกลอุบายเก่าที่คิดค้นเพื่อหลีกเลี่ยงข้อ จำกัด ด้านความปลอดภัยที่ห้ามไม่ให้เรารับข้อมูล JSON จากเซิร์ฟเวอร์อื่น ( ต้นกำเนิดที่แตกต่างกัน* )
เคล็ดลับใช้งานได้โดยใช้<script>
แท็กที่ขอ JSON จากสถานที่นั้นเช่น: { "user":"Smith" }
แต่ถูกห่อหุ้มด้วยฟังก์ชันJSONP จริง ("JSON with Padding"):
peopleDataJSONP({"user":"Smith"})
การรับข้อมูลในรูปแบบนี้ทำให้เราสามารถใช้ข้อมูลภายในpeopleDataJSONP
ฟังก์ชั่นของเรา JSONP เป็นแนวปฏิบัติที่ไม่ดีอย่าใช้ (อ่านด้านล่าง)
ปัญหา
บอกว่าเรากำลังการนำบนourweb.com
และเราต้องการที่จะได้รับข้อมูล JSON (หรือข้อมูลดิบใด ๆ จริงๆ) anotherweb.com
จาก ถ้าเราจะใช้คำขอ GET (เช่นXMLHttpRequest
การfetch
โทร$.ajax
ฯลฯ ) เบราว์เซอร์ของเราจะบอกเราว่ามันไม่ได้รับอนุญาตด้วยข้อผิดพลาดที่น่าเกลียดนี้:
วิธีรับข้อมูลที่เราต้องการ ดี<script>
แท็กไม่ได้อยู่ภายใต้ข้อ จำกัด ของเซิร์ฟเวอร์ทั้งหมด (ที่มา *)! นั่นเป็นเหตุผลที่เราสามารถโหลดไลบรารีเช่น jQuery หรือ Google Maps จากเซิร์ฟเวอร์ใด ๆ เช่น CDN โดยไม่มีข้อผิดพลาด
จุดสำคัญ : ถ้าคุณคิดเกี่ยวกับมันไลบรารีเหล่านั้นเป็นรหัส JS ที่ทำงานได้จริง แต่ข้อมูลดิบ JSON ข้อมูลไม่ได้รหัส ไม่มีอะไรจะวิ่ง มันเป็นเพียงข้อมูลธรรมดา
ดังนั้นจึงไม่มีวิธีจัดการหรือจัดการกับข้อมูลที่มีค่าของเรา เบราว์เซอร์จะดาวน์โหลดข้อมูลที่ระบุโดย<script>
แท็กของเราและเมื่อประมวลผลข้อมูลจะบ่นอย่างถูกต้อง:
{"user":"Smith"}
เราจะโหลดอึนี้ไหม มันไม่ใช่รหัส ฉันไม่สามารถคำนวณข้อผิดพลาดทางไวยากรณ์ได้!
แฮ็ค JSONP
วิธีเก่า / แฮ็กในการใช้ข้อมูลนั้น? เราต้องการเซิร์ฟเวอร์นั้นเพื่อส่งด้วยตรรกะบางอย่างดังนั้นเมื่อโหลดแล้วโค้ดของคุณในเบราว์เซอร์จะสามารถใช้ข้อมูลดังกล่าวได้ ดังนั้นเซิร์ฟเวอร์ต่างประเทศจะส่งข้อมูล JSON ให้เราภายในฟังก์ชัน JS ข้อมูลถูกตั้งค่าเป็นอินพุตของฟังก์ชันนั้น ดูเหมือนว่านี้:
peopleDataJSONP({"user":"Smith"})
ซึ่งทำให้มันเป็นรหัส JSเบราว์เซอร์ของเราจะแยกวิเคราะห์โดยไม่ต้องบ่น! เหมือนกับที่ทำกับไลบรารี jQuery ตอนนี้เพื่อให้เป็นเช่นนั้นลูกค้า "ถาม" เซิร์ฟเวอร์ที่เป็นมิตรกับ JSONP สำหรับมันมักจะทำเช่นนี้:
<script src="https://anotherweb.com/api/data-from-people.json?myCallback=peopleDataJSONP"></script>
เบราว์เซอร์ของเราจะได้รับ JSONP ด้วยชื่อฟังก์ชั่นนั้นดังนั้นเราต้องการฟังก์ชั่นที่มีชื่อเดียวกันในรหัสของเราดังนี้:
const peopleDataJSONP = function(data){
alert(data.user); // "Smith"
}
หรือเช่นนี้ผลลัพธ์เดียวกัน:
function peopleDataJSONP(data){
alert(data.user); // "Smith"
}
เบราว์เซอร์จะดาวน์โหลด JSONP และเรียกใช้ซึ่งเรียกฟังก์ชันของเราซึ่งอาร์กิวเมนต์data
จะเป็น JSON ของเรา ตอนนี้เราสามารถทำอะไรกับข้อมูลของเราสิ่งที่เราต้องการ
อย่าใช้ JSONP ใช้ CORS
JSONP เป็นแฮ็คข้ามไซต์ที่มีข้อเสียเล็กน้อย:
- เราสามารถดำเนินการตามคำขอ GET เท่านั้น
- เนื่องจากเป็นคำขอ GET ที่ถูกเรียกโดยแท็กสคริปต์อย่างง่ายเราจึงไม่ได้รับข้อผิดพลาดที่เป็นประโยชน์หรือข้อมูลความคืบหน้า
- นอกจากนี้ยังมีข้อกังวลด้านความปลอดภัยเช่นทำงานในรหัส JS ลูกค้าของคุณที่สามารถเปลี่ยนเป็นเพย์โหลดที่เป็นอันตราย
- มันแก้ปัญหาข้อมูล JSON ได้ แต่นโยบายความปลอดภัย Same-Origin ใช้กับข้อมูลอื่น ๆ (WebFonts รูปภาพ / วิดีโอที่วาดด้วย drawImage () ... )
- มันไม่ได้สวยงามและอ่านง่าย
Takeaway ที่เป็นว่ามีความจำเป็นต้องใช้มันในปัจจุบัน
JSONP เป็นเคล็ดลับในการรับข้อมูล JSON จากเซิร์ฟเวอร์อื่น แต่เราจะละเมิดหลักการความปลอดภัยเดียวกัน (Same-Origin) หากเราต้องการสิ่งข้ามไซต์ชนิดอื่น
คุณควรอ่านเกี่ยวกับ CORS ที่นี่แต่ส่วนสำคัญของมันคือ:
การแบ่งปันทรัพยากรข้ามแหล่งกำเนิด (CORS) เป็นกลไกที่ใช้ส่วนหัว HTTP เพิ่มเติมเพื่อบอกเบราว์เซอร์เพื่อให้เว็บแอปพลิเคชันทำงานที่แหล่งกำเนิดเดียวเข้าถึงทรัพยากรที่เลือกจากแหล่งกำเนิดที่แตกต่างกัน เว็บแอ็พพลิเคชันเรียกใช้การร้องขอ HTTP ข้ามต้นทางเมื่อร้องขอทรัพยากรที่มีต้นกำเนิดที่แตกต่างกัน (โดเมนโปรโตคอลหรือพอร์ต) จากของตนเอง
* ต้นกำเนิดจะถูกกำหนดโดย 3 สิ่ง: โพรโทคอ , พอร์ตและโฮสต์ ตัวอย่างเช่นhttps://web.com
เป็นแหล่งกำเนิดที่แตกต่างจากhttp://web.com
(โปรโตคอลที่แตกต่าง) และhttps://web.com:8081
(พอร์ตที่แตกต่าง) และเห็นได้ชัดhttps://thatotherweb.net
(โฮสต์ที่แตกต่างกัน)