JSONP eller "JSON with padding" er en tilføjelse til det grundlæggende JSON-format . Det giver en måde at anmode om data fra en server på et andet domæne, en handling, der er forbudt i typiske webbrowsere på grund af domænebegrænsningspolitik .
I juli 2005 foreslog George Jempty muligheden for at forudsætte JSON med en valgfri variabelerklæring. [1] [2] Det originale JSONP-forslag, hvor polstringen er en tilbagekaldsfunktion, blev højst sandsynligt lavet af Bob Ippolito i december 2005 [3] og bruges nu af mange Web 2.0- applikationer såsom Dojo Toolkit , Google Web Toolkit , [4] og webtjenester .
Ifølge domænebegrænsningspolitikken kan en webside på en server example1.comikke kontakte en anden server end example2.com. JSONP-teknologien er baseret på, at browserens sikkerhedspolitik ikke forbyder brugen af et HTML-element <script type="text/javascript" src="…"/> for at få adgang til andre servere end den server, hvorfra siden blev indlæst. Ved at bruge Open Policy on Elements <script>bruger nogle sider dem til at indlæse JavaScript-kode, der fungerer på dynamisk genererede JSON-data fra andre kilder. Anmodninger om JSONP modtager ikke JSON, men vilkårlig JavaScript-kode. De behandles af JavaScript-fortolkeren, ikke af JSON-parseren. Der er alvorlige sikkerhedsrisici ved brug af JSONP, i de fleste situationer er CORS det bedste valg.
Skemaet for mønsteret kan beskrives ved hjælp af en anmodning til en bestemt URL , der returnerer JSON-data. Et JavaScript-program kunne anmode om denne URL, for eksempel via XMLHttpRequest . Antag, at bruger-id'et for Foo-objektet er 1234. En browser , der anmoder om en URL http://server2.example.com/Users/1234, der sender et id på 1234, vil modtage et svar i følgende format:
{ "Name" : "Foo" , "Id" : 1234 , "Rank" : 7 }JSON-dataene i et tredjepartssvar genereres normalt dynamisk baseret på anmodningsparametrene, der sendes i URL'en.
Følgende HTML-element <script>angiver som en attribut et srclink, der returnerer JSON:
< script type = "application/javascript" src = "http://server2.example.com/Users/1234" > </ script >Til gengæld vil browseren downloade filen script, analysere dens indhold, fortolke de rå JSON-data som en blok og kaste en syntaksfejl. Selvom data er blevet fortolket som et JavaScript-objektliteral, kan det ikke tilgås fra JavaScript, der kører i browseren, fordi objektliteraler ikke er tilgængelige uden at være tildelt en variabel.
I JSONP-mønsteret returnerer URL'en, der peges på af taggens <script>src-attribut, JSON-data pakket ind i et funktionskald. I et sådant tilfælde kan en funktion, der allerede er defineret i JavaScript-miljøet, manipulere JSON-data. JSONP-fyldningen kan se sådan ud:
functionCall ({ "Name" : "Foo" , "Id" : 1234 , "Rank" : 7 });Funktionskaldet er "P" i JSONP-ordet - "padding" (fyldning, " indrykning ") omkring ren JSON, eller ifølge nogle kilder [5] - "præfiks". Efter konvention videregiver browseren navnet på tilbagekaldsfunktionen som en navngivet anmodningsparameter, normalt ved at bruge navnet jsonpeller callbacki anmodningen til serveren, dvs.
< script type = "text/javascript" src = "http://server2.example.com/Users/1234?jsonp=parseResponse" > </ script >I dette eksempel vil fyldet være som følger:
parseResponse ({ "Name" : "Foo" , "Id" : 1234 , "Rank" : 7 });Hvorimod udfyldningen (præfikset) normalt er navnet på en tilbagekaldsfunktion, der er defineret i udførelseskonteksten i browseren. Ud over funktionsnavnet kan præfikset betyde et variabelnavn, en operator ifeller en hvilken som helst anden JavaScript-operator. Svaret på en JSONP-anmodning (strengt taget en anmodning, der er i overensstemmelse med JSONP-mønsteret) er ikke et JSON-objekt og behandles ikke som sådan af browseren. "Stuffing" kan være et hvilket som helst JavaScript-udtryk og kræver ikke, at JSON er inde. Men det er normalt et stykke JavaScript, der anvender et funktionskald på nogle JSON-data.
Med andre ord giver en typisk brug af JSONP adgang på tværs af domæner til en eksisterende JSON API ved at indpakke JSON-fyldningen i et funktionskald.
JSONP giver kun mening, når den bruges sammen med et script-element. For hver ny JSONP-anmodning skal browseren tilføje et nyt element <script>eller bruge et eksisterende. Den første manipulation, tilføjelse af et nyt script-element, udføres gennem dynamisk DOM-manipulation, og er kendt som script element injection . Elementet <script>indsættes i HTML DOM, med URL'en for det ønskede JSONP slutpunkt i "src" attributten.
Denne dynamiske scriptelementindsprøjtning udføres normalt af et JavaScript-hjælpebibliotek. jQuery og andre rammer har hjælpefunktioner til JSONP; der er også separate løsninger [6] [7] .
Det dynamisk indsatte script-element til JSONP-kald ser sådan ud:
< script type = "text/javascript" src = "http://server2.example.com/Users/1234?jsonp=parseResponse" > </ script >Efter at elementet er indsat, behandler browseren det og udfører en HTTP GET på src URL'en og henter indholdet. Browseren behandler derefter den returnerede nyttelast som JavaScript. Normalt er dette udførelsen af en funktion.
I denne forstand kan brugen af JSONP beskrives som at tillade browsersider at omgå domænebegrænsningspolitikken ved at indsætte et script-element.
Inkludering af script-tags fra andre servere giver fjernservere mulighed for at blande ethvert indhold på webstedet . Hvis fjernservere har sårbarheder, der tillader JavaScript at blive blandet ind, er siden leveret af den originale server i øget risiko.
Der tages i øjeblikket skridt til at definere en mere sikker, streng delmængde af JSON-P [8] , som browsere kan tvinge til at inkludere, når de anmoder om et script med en specifik MIME-type, såsom "application/json-p". Hvis svaret ikke er parset som strengt JSON-P, kan browseren give en fejl eller blot ignorere hele svaret. Men i øjeblikket er den eneste gyldige MIME-type for JSONP "application/javascript" [9] .
Primitive JSONP-værter er modtagelige for forfalskning af anmodninger på tværs af websteder (CSRF eller XSRF) [10] . Fordi HTML-tagget <script>ikke er underlagt domænebegrænsningspolitikken i rigtige browserimplementeringer, kan en ondsindet side anmode om og modtage JSON-data, der tilhører et andet websted. Dette vil tillade, at JSON-dataene kan behandles i sammenhæng med en ondsindet side, hvilket muligvis afslører adgangskoder eller andre følsomme data, hvis brugeren er logget ind på et andet websted.
Dette giver kun problemer, hvis de JSON-kodede data indeholder følsomme oplysninger, som ikke bør videregives til en tredjepart, og serveren er afhængig af browserens domænebegrænsningspolitik for at blokere datatransmission i tilfælde af en dårlig anmodning. Problemet eksisterer ikke, hvis serveren selv bestemmer, om anmodningen er passende, idet den kun sender data, hvis anmodningen er gyldig. Cookies i sig selv er ikke en tilstrækkelig måde at bestemme legitimiteten af en anmodning. Brugen af cookies alene er modtagelig for forfalskning af anmodninger på tværs af websteder .
JSONPP ( eng. parameteriseret JSON med polstring - "parameteriseret JSON med polstring") - udviklingen af JSONP-ideen.
JSONPP inkluderer kilde-URL'en, navnet på den funktion, der skal behandle JSON-dataene, strengen, der skal evalueres, efter at dataene er modtaget, og strengen, der skal evalueres, når dataene er færdige:
JSON_call ( SRC , JSONP , JSONPP , ONLOAD );vender til sidst om
ans = JSONP ( SRC ) { eval ( JSONPP ( ans )); eval ( ONLOAD ); }Generelt er antallet af parametre ikke vigtigt for selve JSONPP-ideen. SRC, JSONP, JSONPP (og deres behandling på serversiden og derefter klientsiden) er nok til at det er JSONPP. Overvej eksemplet med at arbejde med S3DB-tjenesten.
funktion s3db_jsonpp_call ( src , next_eval ){ var call = "call_" + Math . tilfældig (). toString (). erstatte ( /\./g , "" ); var headID = dokument . getElementsByTagName ( "hoved" )[ 0 ]; var script = dokument . createElement ( 'script' ); script . id = opkald ; script . type = 'tekst/javascript' ; // ved hjælp af polstret, parameteriseret json src = src + "&format=json&jsonp=s3db_jsonpp&jsonpp=" + next_eval + "&onload=remove_element_by_id('" + script . id + "')" ; script . src = src ; hoved-ID . appendChild ( script ); // hente svar } funktion s3db_jsonpp ( ans , jsonpp ) { eval ( jsonpp ); returnere ans ; } funktion remove_element_by_id ( id ){ var e = document . getElementById ( id ); e . parentNode . fjernBarn ( e ); returnere falsk ; }I eksemplet s3db_jsonpp_call()opretter funktionen et script-element i hoveddelen af DOM, hvis src matcher JSONPP-kaldet.
Efter at have modtaget et svar fra serveren vil det blive kaldt s3db_jsonpp() - det videregives i opkaldsparametrene, som det skal være ifølge JSONP regler.
Internt s3db_jsonpp()vil fungere eval(jsonpp), og værdien af ans vil blive returneret.
Kaldet eval(onload)fører til eksekvering remove_element_by_id()med id'et af det oprettede script i head og som følge heraf til sletning, fordi det alligevel ikke længere vil blive brugt, da id'et i eksemplet blev tilfældigt genereret helt i begyndelsen af funktionen s3db_jsonpp_call(). Dette opkald er i serverens svar.