TL; DR
JSONP, farklı bir sunucudan JSON verisi almamızı engelleyen güvenlik kısıtlamasını atlamak için icat edilen eski bir numaradır (farklı bir kaynak * ).
Hile <script>
, o yerden JSON isteyen bir etiket kullanarak çalışır , örneğin:, { "user":"Smith" }
ancak gerçek JSONP ("Padding ile JSON"):
peopleDataJSONP({"user":"Smith"})
Bu formda almak, peopleDataJSONP
fonksiyonumuzdaki verileri kullanmamızı sağlar . JSONP kötü bir uygulamadır , kullanmayın (aşağıyı okuyun)
Sorun
Gezintiğimizi ourweb.com
ve JSON verilerini (veya gerçekten herhangi bir ham veriyi) almak istediğimizi varsayalım anotherweb.com
. Biz GET isteği kullanmak için olsaydı (gibi XMLHttpRequest
bir, fetch
çağrı, $.ajax
vb), bizim tarayıcı bu çirkin hata ile izin verilmez bize anlatırdı:
İstediğimiz veriler nasıl elde edilir? Eh, <script>
etiketler Bütün bu sunucu (orijin *) kısıtlamaya tabi değildir! Bu nedenle CDQ gibi herhangi bir sunucudan jQuery veya Google Haritalar gibi bir kitaplığı hatasız yükleyebiliriz.
Önemli nokta : Eğer düşünürseniz, bu kütüphaneler gerçek, çalıştırılabilir JS kodudur (genellikle içindeki tüm mantıkla büyük bir işlevdir). Peki ham veriler? JSON verileri kod değildir . Kaçacak bir şey yok; sadece düz veri.
Bu nedenle, değerli verilerimizi işlemenin veya işlememenin bir yolu yoktur. Tarayıcı, etiketimizin işaret ettiği verileri indirir <script>
ve işlerken haklı olarak şikayet eder:
wtf {"user":"Smith"}
yüklediğimiz bu saçmalık mı? Kod değil. Hesaplayamıyorum, sözdizimi hatası!
JSONP kesmek
Bu verileri kullanmanın eski / hacky yolu? Bu sunucunun bir mantık göndermesi gerekiyor, bu yüzden yüklendiğinde tarayıcıdaki kodunuz söz konusu verileri kullanabilecektir. Yabancı sunucu bize JSON verilerini bir JS işlevi içinde gönderir. Verilerin kendisi bu işlevin girdisi olarak ayarlanır. Şöyle görünüyor:
peopleDataJSONP({"user":"Smith"})
Bu da tarayıcımızın şikayet etmeden ayrışacağı JS kodunu yapar ! Tam olarak jQuery kütüphanesinde olduğu gibi. Şimdi, bu şekilde elde etmek için, istemci genellikle böyle yapılan JSONP dostu sunucuyu "sorar":
<script src="https://anotherweb.com/api/data-from-people.json?myCallback=peopleDataJSONP"></script>
Tarayıcımız JSONP'u bu işlev adıyla alacaktır, bu nedenle kodumuzda aynı ada sahip bir işleve ihtiyacımız var, şöyle:
const peopleDataJSONP = function(data){
alert(data.user); // "Smith"
}
Veya bunun gibi, aynı sonuç:
function peopleDataJSONP(data){
alert(data.user); // "Smith"
}
Tarayıcı JSONP'yi indirecek ve işlevimizi çağıran argümanın data
JSON olacağı yerde çalıştıracaktır . Artık verilerimizle ne yapmak istiyorsak yapabiliriz.
JSONP kullanmayın, CORS kullanın
JSONP, birkaç dezavantajı olan siteler arası bir kesmek:
- Yalnızca GET isteklerini gerçekleştirebiliriz
- Basit bir komut dosyası etiketi tarafından tetiklenen bir GET isteği olduğundan, yararlı hatalar veya ilerleme bilgileri almıyoruz
- Ayrıca, istemci JS kodunuzda kötü amaçlı bir yüke değiştirilebilecek bazı güvenlik sorunları da vardır.
- Yalnızca JSON verileriyle ilgili sorunu çözer, ancak Aynı Kökenli güvenlik ilkesi diğer veriler için geçerlidir (WebFonts, drawImage () ile çizilen resimler / video ...)
- Çok zarif veya okunabilir değil.
Paket servisi, bugünlerde kullanmaya gerek yoktur .
JSONP, başka bir sunucudan JSON verisi almanın hilesidir, ancak başka tür siteler arası içeriklere ihtiyacımız olursa aynı güvenlik ilkesini (Aynı Kökenli) ihlal ederiz.
Sen gerektiğini burada CORS hakkında okumak , ama bunun özü şudur:
Kaynaklar Arası Kaynak Paylaşımı (CORS), tarayıcılara bir kaynaktan çalışan bir web uygulamasına farklı kaynaklardan seçilen kaynaklara erişim vermelerini bildirmek için ek HTTP üstbilgileri kullanan bir mekanizmadır. Bir web uygulaması, kendisinden farklı bir kaynağı (etki alanı, protokol veya bağlantı noktası) olan bir kaynak istediğinde bir çapraz kökenli HTTP isteği yürütür.
* orijin 3 şeyle tanımlanır: protokol , port ve ana bilgisayar . Bu nedenle, örneğin, https://web.com
farklı bir daha kökeni http://web.com
(farklı protokolü) ve https://web.com:8081
açıkçası (farklı bağlantı noktası) ve https://thatotherweb.net
(farklı konakçı)