当前位置: 首页 > Web前端 > JavaScript

JSONP跨域原理与实现

时间:2023-03-27 12:05:22 JavaScript

鍓嶈█鍦ㄦ棩甯哥殑椤圭洰寮€鍙戣繃绋嬩腑锛岃法鍩熶互鍙婂浣曡В鍐宠法鍩熼棶棰樻槸鍓嶅悗绔紑鍙戝悓瀛︾粫涓嶅紑鐨勮瘽棰樸€侸SONP璺ㄥ煙鏄法鍩熼棶棰樼殑缁忓吀瑙e喅鏂规銆傪煉℃俯棣ㄦ彁绀猴細鏈枃鍏ㄦ枃1921瀛楋紝寤鸿闃呰鏃堕棿10鍒嗛挓銆傚姞娌癸紝鑰佸叺锛?.鍚屾簮绛栫暐涓庤法鍩?.1鍚屾簮绛栫暐1.1.1浠€涔堟槸鍚屾簮濡傛灉涓や釜椤甸潰鐨勫崗璁€佸煙鍚嶃€佺鍙g浉鍚岋紝鍒欎袱涓〉闈㈠悓婧?//www.test.com/index.html椤甸潰鍚屾簮妫€娴嬶細1.1.2浠€涔堟槸鍚屾簮绛栫暐鍚屾簮绛栫暐锛堣嫳鏂囧叏绉癝ameoriginpolicy锛夋槸娴忚鍣ㄦ彁渚涚殑涓€绉嶅畨鍏ㄧ壒鎬с€侻DN鐨勫畼鏂规蹇碉細鍚屾簮绛栫暐闄愬埗浜嗕粠鍚屼竴婧愬姞杞界殑鏂囨。鎴栬剼鏈浣曚笌鍙︿竴涓簮鐨勮祫婧愯繘琛屼氦浜掋€傝繖鏄殧绂绘綔鍦ㄦ伓鎰忔枃浠剁殑閲嶈瀹夊叏鏈哄埗銆傞€氫織鐞嗚В锛氭祻瑙堝櫒瑙勫畾锛孉缃戠珯鐨凧avaScript锛屼笉鍏佽涓庨潪鍚屾簮缃戠珯C杩涜璧勬簮浜や簰锛屼緥濡傦細鏃犳硶璇诲彇闈炲悓婧愮綉椤电殑cookie锛孡ocalStorage鍜孖ndexedDB鏃犳硶璁块棶闈炲悓婧?婧愮珯缃戦〉鐨凞OM涓嶈兘鍚戦潪鍚屾簮鍦板潃鍙戦€丄JAX璇锋眰1.2璺ㄥ煙1.2.1浠€涔堟槸璺ㄥ煙鍚屾簮鏄寚涓や釜URL鐨勫崗璁€佸煙鍚嶃€佺鍙f槸鐩稿悓锛屽弽涔嬶紝鍒欎负璺ㄥ煙銆傝法鍩熺殑鏍规湰鍘熷洜锛氭祻瑙堝櫒鐨勫悓婧愮瓥鐣ヤ笉鍏佽闈炲悓婧怳RL涔嬮棿鐨勮祫婧愪氦浜掋€傜綉椤碉細http://www.test.com/index.html鎺ュ彛锛歨ttp://www.api.com/userlist1.2.2娴忚鍣ㄦ嫤鎴法鍩熻姹傛敞鎰忥細娴忚鍣ㄥ厑璁歌法鍩熻姹傦紝浣嗘槸锛岃法鍩熻姹傝繑鍥炵殑鏁版嵁浼氳娴忚鍣ㄦ嫤鎴紝椤甸潰鏃犳硶鑾峰彇锛?.2.3濡備綍瀹炵幇璺ㄥ煙鏁版嵁璇锋眰瀹炵幇璺ㄥ煙鏁版嵁璇锋眰鐨勬柟寮忔湁寰堝锛屾瘮濡侸SONP銆丆ORS銆乸ostMessage銆乄ebsocket銆丯ginx鍙嶅悜浠g悊銆亀indow.name+iframe銆乨ocument.domain+iframe銆乴ocation.hash+iframe绛夈€備笁绉嶄富瑕佺殑瑙e喅鏂规鏄疛SONP銆丆ORS鍜孨ginx鍙嶅悜浠g悊銆侸SONP锛氬嚭鐜拌緝鏃╋紝鍏煎鎬уソ锛堝吋瀹逛綆鐗堟湰IE锛夈€傛槸鍓嶇绋嬪簭鍛樹负浜嗚В鍐宠法鍩熼棶棰樿杩兂鍑虹殑涓存椂鏂规銆傜己鐐规槸鍙敮鎸丟ET璇锋眰锛屼笉鏀寔POST璇锋眰銆侰ORS锛氬嚭鐜拌緝鏅氾紝鏄疻3C鏍囧噯锛屾槸璺ㄥ煙AJAX璇锋眰鐨勬牴鏈В鍐虫柟妗堛€傛敮鎸丟ET鍜孭OST璇锋眰銆傜己鐐规槸涓嶅吋瀹逛竴浜涗綆鐗堟湰鐨勬祻瑙堝櫒銆侼ginx鍙嶅悜浠g悊锛氬悓婧愮瓥鐣ワ紝瀵规湇鍔″櫒娌℃湁浠讳綍闄愬埗锛屾槸鏈€绠€鍗曠殑璺ㄥ煙鏂瑰紡銆傚彧闇€瑕佷慨鏀筺ginx鐨勯厤缃嵆鍙В鍐宠法鍩熼棶棰橈紝鏀寔鎵€鏈夋祻瑙堝櫒锛屾敮鎸乻ession锛屼笉闇€瑕佷慨鏀逛换浣曚唬鐮侊紝涓嶄細褰卞搷鏈嶅姟鍣ㄦ€ц兘銆備簩銆丣SONP姒傝堪JSONP锛圝SONwithPadding锛夋槸JSON鐨勪竴绉嶁€滀娇鐢ㄦ柟寮忊€濓紝鍙互鐢ㄦ潵瑙e喅涓绘祦娴忚鍣ㄧ殑璺ㄥ煙鏁版嵁璁块棶闂銆?.1JSONP鍘熺悊棰勫厛瀹氫箟涓€涓幏鍙栬法鍩熷搷搴旀暟鎹殑鍥炶皟鍑芥暟锛岄€氳繃script鏍囩鍙戣捣璇锋眰锛屼笉鍙楀悓婧愮瓥鐣ョ殑闄愬埗锛堝皢鍥炶皟鍑芥暟鍚嶆斁鍦ㄨ姹傜殑鏌ヨ鍙傛暟涓級request)锛岀劧鍚庢湇鍔$杩斿洖鎵ц鍥炶皟鍑芥暟锛屽皢闇€瑕佸搷搴旂殑鏁版嵁鏀惧叆鍥炶皟鍑芥暟鐨勫弬鏁颁腑銆傚墠绔痵cript鏍囩璇锋眰鎵ц鐨勫洖璋冨嚱鏁板悗锛屼細绔嬪嵆鎵ц锛屾墍浠ュ緱鍒版墽琛岀殑鍝嶅簲鏁版嵁銆?.2浼樼偣涓嶅儚XMLHttpRequest瀵硅薄瀹炵幇鐨凙jax璇锋眰閭f牱鍙楀悓婧愮瓥鐣ョ殑闄愬埗銆傚畠鍏锋湁鏇村ソ鐨勫吋瀹规€э紝鍙互鍦ㄦ棫娴忚鍣ㄤ腑杩愯銆備笉闇€瑕乆MLHttpRequest鎴朅ctiveX鐨勬敮鎸侊紝璇锋眰瀹屾垚鍚庡嵆鍙紶閫掋€?.3缂虹偣锛氬彧鏀寔GET璇锋眰锛屼笉鏀寔POST绛夊叾浠栫被鍨嬬殑HTTP璇锋眰銆傚畠鍙敮鎸佽法鍩烪TTP璇锋眰銆傚畠鏃犳硶瑙e喅濡備綍鍦ㄤ笉鍚屽煙鐨勪袱涓〉闈箣闂磋繘琛孞avaScript璋冪敤鐨勯棶棰樸€傞棶棰?.JSONP鐢宠娴佺▼璁剧疆涓€涓剼鏈爣绛?scriptsrc="http://jsonp.js?callback=cb">//鎴栬€呰script=document.createElement('script');script銆俿rc="http://jsonp.js?callback=cb";body.append(script)callback瀹氫箟浜嗕竴涓嚱鏁板悕锛岃繙绋嬫湇鍔″櫒閫氳繃璋冪敤鎸囧畾鐨勫嚱鏁板苟浼犲叆鍙傛暟鏉ュ疄鐜颁紶閫掑弬鏁帮紝function(response)浼犻€掕繑鍥炲鎴风router.get('/',function(req,res,next){(()=>{constdata={x:10};letparams=req.query;if(params.callback){letcallback=params.callback;console.log(params.callback);res.send(`${callback}(${JSON.stringify(data.x)})`);}else{res.send('err');}})();});瀹㈡埛绔敹鍒拌繑鍥炵殑JS鑴氭湰鍚庯紝寮€濮嬭В鏋愬苟鎵цfunction(response)4.JSONP瀹炵幇3.1绠€鍗曠ず渚嬶細涓€涓畝鍗曠殑JSONP瀹炵幇锛屽叾瀹炲氨鏄嫾鎺rl锛岀劧鍚庡湪澶撮儴鍔ㄦ€佹坊鍔犱竴涓猻cript鍏冪礌鍓嶇JSONP鏂规硶绀轰緥锛歠unctionjsonp(req){varscript=document.createElement('script');varurl=req.url+'?callback='+req.callback.name;鑴氭湰.src=url;鏂囨。銆俫etElementsByTagName('head')[0].appendChild(script);}鍓嶇JS绀轰緥锛歠unctionhello(res){alert('hello'+res.data);}jsonp({url:'',callback:浣犲ソ});鏈嶅姟鍣ㄤ唬鐮侊細varhttp=require('http');varurllib=require('url');varport=8080;vardata={'data':'world'};http.createServer(function(req,res){varparams=urllib.parse(req.url,true);if(params.query.callback){console.log(params.query.callback);//jsonpvarstr=params.query.鍥炶皟+'('+JSON.stringify(data)+')';res.end(str);}else{res.end();}}).listen(port,function(){console.log('jsonp鏈嶅姟鍣ㄥ紑鍚?);});3.2鍙潬鐨凧SONP瀹炰緥:(function(global){varid=0,container=document.getElementsByTagName("head")[0];functionjsonp(options){if(!options||!options.url)杩斿洖锛泇arscriptNode=document.createElement("鑴氭湰"),data=options.data||{},url=options.url,callback=options.callback,fnName="jsonp"+id++;//娣诲姞鍥炶皟鍑芥暟data["callback"]=fnName;//鎷兼帴urlvarparams=[];for(varkeyindata){params.push(encodeURIComponent(key)+"="+encodeURIComponent(data[key]));}url=url.indexOf("?")>0?(url+"&"):(url+"?");url+=params.join("&");scriptNode.src=url;//浼犲叆鐨勬槸鍖垮悕鍥炶皟鍑芥暟锛屽鏋滆鎵ц锛屾毚闇蹭负鍏ㄥ眬鏂规硶global[fnName]=function(ret){callback&&callback(ret);container.removeChild(scriptNode);鍒犻櫎鍏ㄥ眬[fnName]锛泒//閿欒澶勭悊scriptNode.onerror=function(){鍥炶皟&&鍥炶皟锛坽閿欒锛氣€滈敊璇€潁锛夛紱container.removeChild(scriptNode);global[fnName]&&deleteglobal[fnName];}scriptNode.type="text/javascript";container.appendChild(scriptNode)}global.jsonp=jsonp;})(this);绀轰緥锛歫sonp({url:"www.example.com",data:{id:1},callback:function(ret){console.log(ret);}});浜斻€丣SONP瀹夊叏闂5.1CSRF鏀诲嚮鍓嶇鏋勯€犳伓鎰忛〉闈紝璇锋眰JSONP鎺ュ彛锛屽湪鏈嶅姟鍣ㄧ瀹夊叏鏀堕泦鏁忔劅淇℃伅銆傝В鍐虫柟妗堬細楠岃瘉JSONP鐨勮皟鐢ㄦ簮锛圧eferer锛夛紝鏈嶅姟绔垽鏂璕eferer鏄惁鍦ㄧ櫧鍚嶅崟涓紝鎴栬€呴儴缃蹭竴涓殢鏈虹殑Token杩涜闃插尽銆?.2XSS婕忔礊content-type涓嶇簿纭鑷寸殑XSS婕忔礊锛屽亣璁綣SONP鏄綘璇锋眰http://abc.com?callback=douniwan锛岀劧鍚庤繑鍥瀌ouniwan({data})锛岄偅涔堝鏋滀綘璇锋眰http://abc銆俢om?callback=灏嗚繑鍥?script>alert(1)({data})锛屽鏋淐ontent-Type娌℃湁涓ユ牸瀹氫箟(Content-Type:application/json锛夛紝骞朵笖涓嶈繃婊ゅ洖璋冨弬鏁帮紝濡傛灉鐩存帴瑙f瀽鎴怘TML锛屽氨鏄8XSS銆傝В鍐虫柟娉曪細涓ユ牸瀹氫箟Content-Type锛歛pplication/json锛岀劧鍚庡鍥炶皟鍚庣殑鍙傛暟杩涜涓ユ牸杩囨护锛岄檺鍒堕暱搴︼紙杞箟瀛楃锛屾瘮濡傚皢<鏇挎崲涓?lt锛?鏇挎崲涓?gt锛夌瓑锛岃繖鏍疯繑鍥炵殑鑴氭湰鍐呭灏嗗彉鎴愭枃鏈牸寮忥紝鑴氭湰灏嗕笉浼氭墽琛屻€?.3鏈嶅姟鍣ㄨ榛戯紝杩斿洖涓€涓叉伓鎰忎唬鐮併€傚彲浠ュ皢鎵ц鐨勪唬鐮佽浆鍙戠粰鏈嶅姟鍣ㄨ繘琛屾牎楠孞SONP鍐呭鏍¢獙锛岀劧鍚庤繑鍥炴牎楠岀粨鏋溿€傚弬鑰僇SONP瀹夊叏璺ㄥ煙鍜屽墠绔篃闇€瑕佷簡瑙g殑JSONP