【黑馬程序員濟南中心】跨域請求之JSONP蚊伞、CORS淺談

1.為什么會有跨域席赂?

? ?? ?隨著軟件開發(fā)分工趨于精細(xì),前后端開發(fā)分離成為趨勢时迫,前端同事負(fù)責(zé)前端頁面的展示及頁面邏輯處理颅停,服務(wù)端同事負(fù)責(zé)業(yè)務(wù)邏輯處理同時通過API為前端提供數(shù)據(jù)也為前端提供數(shù)據(jù)的持久化能力,考慮到前后端同事開發(fā)工具和習(xí)慣的不同掠拳,必然需要將前后端項目進行獨立癞揉,再者考慮到網(wǎng)站訪問速度的問題,需要將靜態(tài)資源部署到CDN服務(wù)器上這樣項目分離也成為了必然溺欧。然而項目分離部署分離帶來的問題就是跨域請求的問題喊熟。

本例對比較流行的兩種跨域訪問方式(Jsonp和CORS)進行討論。(注:示例代碼附在文章末尾處)

1.JSONP

? ?? ?JSONP是利用瀏覽器對script的資源引用沒有同源限制姐刁,通過動態(tài)插入一個script標(biāo)簽芥牌,當(dāng)資源加載到頁面后會立即執(zhí)行的原理實現(xiàn)跨域的。JSONP是一種非正式傳輸協(xié)議龙填,該協(xié)議的一個要點就是允許用戶傳遞一個callback或者開始就定義一個回調(diào)方法胳泉,參數(shù)給服務(wù)端,然后服務(wù)端返回數(shù)據(jù)時會將這個callback參數(shù)作為函數(shù)名來包裹住JSON數(shù)據(jù)岩遗,這樣客戶端就可以隨意定制自己的函數(shù)來自動處理返回數(shù)據(jù)了扇商。

  JSONP只支持GET請求而不支持POST等其它類型的HTTP請求,它只支持跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript調(diào)用的問題宿礁,JSONP的優(yōu)勢在于支持老式瀏覽器案铺,弊端也比較明顯:需要客戶端和服務(wù)端定制進行開發(fā),服務(wù)端返回的數(shù)據(jù)不能是標(biāo)準(zhǔn)的Json數(shù)據(jù)梆靖,而是callback包裹的數(shù)據(jù)控汉。

2.CORS

  CORS是現(xiàn)代瀏覽器支持跨域資源請求的一種方式,全稱是"跨域資源共享"(Cross-origin resource sharing)返吻,當(dāng)使用XMLHttpRequest發(fā)送請求時姑子,瀏覽器發(fā)現(xiàn)該請求不符合同源策略,會給該請求加一個請求頭:Origin测僵,后臺進行一系列處理街佑,如果確定接受請求則在返回結(jié)果中加入一個響應(yīng)頭:Access-Control-Allow-Origin;瀏覽器判斷該相應(yīng)頭中是否包含Origin的值谢翎,如果有則瀏覽器會處理響應(yīng),我們就可以拿到響應(yīng)數(shù)據(jù)沐旨,如果不包含瀏覽器直接駁回森逮,這時我們無法拿到響應(yīng)數(shù)據(jù)。

? ?? ?CORS與JSONP的使用目的相同磁携,但是比JSONP更強大褒侧,CORS支持所有的瀏覽器請求類型,承載的請求數(shù)據(jù)量更大谊迄,開放更簡潔闷供,服務(wù)端只需要將處理后的數(shù)據(jù)直接返回,不需要再特殊處理鳞上。

? ?? ?1.不需要操作cookie

? ?? ?? ?? ?? ? 只需要設(shè)置:setHeader("Access-Control-Allow-Origin","url/*")

? ?? ?2.如果需要操作cookie

? ?? ?? ?? ?? ? 前臺:js需要增加參數(shù):{'withCredentials':true}

? ?? ?? ?? ?? ? 后臺:

? ?? ?? ?? ?? ?? ?? ?? ?setHeader("Access-Control-Allow-Origin","url") //注意:地址不能使用"*"代表所有

? ?? ?? ?? ?? ?? ?? ?? ?setHeader("Access-Control-Allow-Credentials","true") //支持操作cookie

? ?? ???注解方式:spring4.2版本以后提供了對跨域注解的支持这吻,可以使用注解 @CorsOrigin

因需要實現(xiàn)跨域請求,跨域可以是:協(xié)議不一樣,域名不一樣,ip地址不一樣,端口號不一樣等多種情況篙议。為了簡單,下面示例代碼使用tomcat服務(wù)器怠硼,端口號不同鬼贱,分別部署兩個項目,項目之間進行數(shù)據(jù)交互香璃,驗證跨域請求.

2個項目这难,展示如下:


1.JSONP示例代碼:

1.1jsonp前端代碼:(注:代碼在demo1項目中)

function jsonpTest1() {//傳統(tǒng)支持jsonp的方案

? ? ? ? $.ajax({

? ? ? ? url: 'http://localhost:8081/jsonp_demo2/jsonp/test1.do',

? ? ? ? dataType: 'jsonp',

? ? ? ? success: function (res, status, xhr) {

? ? ? ? ? ? ? ? alert(status);

? ? ? ? ? ? ? ? alert(res.msg);

? ? ? ? }

? ? });

}

function jsonpTest2() {//使用MappingJacksonValue,從spring4.1以后版本才可以使用

? ? ? ? $.ajax({

? ? ? ? url: 'http://localhost:8081/jsonp_demo2/jsonp/test2.do',

? ? ? ? dataType: 'jsonp',

? ? ? ? success: function (res, status, xhr) {

? ? ? ? ? ? ? ? alert(status);

? ? ? ? ? ? ? ? var resJson = $.parseJSON(res);

? ? ? ? ? ? ? ? alert(resJson.msg);

? ? ? ? }

? ? });

}

1.2jsonp后臺代碼:(注:代碼在demo2項目中)

/**

* @author:admin

* 20182018年3月30日上午11:03:03

*/

/**

* 描述:

* @author zhuan

* @version 2018年3月30日 上午11:03:03

*/

package com.itcast.controller;

import org.apache.commons.lang3.StringUtils;

import org.springframework.http.converter.json.MappingJacksonValue;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.http.MediaType;

/**

* JS跨域解決方案一

* 描述:JSONP跨域請求controller

* @author zhuan

* @version 2018年3月31日 上午9:58:50

*/

@RestController

@RequestMapping("/jsonp")

public class JsonpController{


? ? ? ? /**

? ? ? ? *

? ? ? ? * 描述:傳統(tǒng)支持jsonp的方案

? ? ? ? * @param param

? ? ? ? * @param callback

? ? ? ? * @return

? ? ? ? */

? ? ? ? @RequestMapping(value = "/test1", produces = MediaType.APPLICATION_JSON_VALUE + ";charset=utf-8")

? ? ? ? public String jsonTest1(String param, String callback) {

? ? ? ? ? ? ? ? if (StringUtils.isNotBlank(callback)) {

? ? ? ? ? ? ? ? ? ? ? ? // 客戶端為jsonp請求葡秒。需要返回js代碼

? ? ? ? ? ? ? ? ? ? ? ? String jsonResutl = callback + "({\"type\":\"json\",\"msg\":\"test1 jsonp request success\"})";

? ? ? ? ? ? ? ? ? ? ? ? return jsonResutl;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? return "{\"type\":\"json\",\"msg\":\"test1 json request success\"}";

? ? ? ? }

? ? ? ? /**

? ? ? ? *

? ? ? ? * 描述:從spring4.1以后版本才可以使用

? ? ? ? *

? ? ? ? * @param param

? ? ? ? * @param callback

? ? ? ? * @return

? ? ? ? */

? ? ? ? @RequestMapping("/test2")

? ? ? ? public Object jsonTest2(String param,String callback){

? ? ? ? ? ? ? ? if(StringUtils.isNotBlank(callback)){

? ? ? ? ? ? ? ? ? ? ? ? MappingJacksonValue mappingJacksonValue = new MappingJacksonValue("{\"type\":\"jsonp\",\"msg\":\"test2 jsonp request success\"}");

? ? ? ? ? ? ? ? ? ? ? ? //設(shè)置回調(diào)方法

? ? ? ? ? ? ? ? ? ? ? ? mappingJacksonValue.setJsonpFunction(callback);

? ? ? ? ? ? ? ? ? ? ? ? return mappingJacksonValue;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? return "{\"type\":\"json\",\"msg\":\"test2 json request success\"}";

? ? ? ? }

}

2.CORS示例代碼:

2.1cors前端代碼:(注:代碼在demo1項目中)

function corsTest() {

? ? ? ? $.ajax({

? ? ? ? url: 'http://localhost:8081/jsonp_demo2/cors/test.do',

? ? ? ? dataType: 'json',

? ? ? ? success: function (res, status, xhr) {

? ? ? ? ? ? ? ? alert(status);

? ? ? ? ? ? ? ? alert(res.msg);

? ? ? ? }

? ? });

}

2.2cors后臺代碼:(注:代碼在demo2項目中)

package com.itcast.controller;

import org.springframework.web.bind.annotation.CrossOrigin;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.web.bind.annotation.RestController;

/**

* JS跨域解決方案二 描述:CORS跨域請求controller

*

* @author zhuan

* @version 2018年3月31日 上午9:58:50

*/

@RestController

@RequestMapping("/cors")

public class CorsController {

? ? ? ? // 1.不支持操作cookie

? ? ? ? // 只需要設(shè)置:setHeader("Access-Control-Allow-Origin","url/*")

? ? ? ? // 2.支持操作cookie

? ? ? ? // 前臺:

? ? ? ? // js需要增加參數(shù):{'withCredentials':true}

? ? ? ? // 后臺:

? ? ? ? // setHeader("Access-Control-Allow-Origin","url") //注意:地址不能使用"*"代表所有

? ? ? ? // setHeader("Access-Control-Allow-Credentials","true") //支持操作cookie

? ? ? ? // 注解方式:spring4.2版本以后提供了對跨域注解的支持 @CorsOrigin

? ? ? ? /**

? ? ? ? *

? ? ? ? * 描述:

? ? ? ? *

? ? ? ? * @param param

? ? ? ? * @param callback

? ? ? ? * @return

? ? ? ? */

? ? ? ? @RequestMapping("/test")

? ? ? ? @CrossOrigin(origins = "http://localhost:8080")

? ? ? ? public String corsTest1(String param) {

? ? ? ? ? ? ? ? return "{\"type\":\"json\",\"msg\":\"cors json request success\"}";

? ? ? ? }

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末姻乓,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子眯牧,更是在濱河造成了極大的恐慌蹋岩,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件学少,死亡現(xiàn)場離奇詭異剪个,居然都是意外死亡,警方通過查閱死者的電腦和手機版确,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進店門扣囊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人绒疗,你說我怎么就攤上這事侵歇。” “怎么了吓蘑?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵惕虑,是天一觀的道長。 經(jīng)常有香客問我,道長枷遂,這世上最難降的妖魔是什么樱衷? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮酒唉,結(jié)果婚禮上矩桂,老公的妹妹穿的比我還像新娘。我一直安慰自己痪伦,他們只是感情好侄榴,可當(dāng)我...
    茶點故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著网沾,像睡著了一般癞蚕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上辉哥,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天桦山,我揣著相機與錄音,去河邊找鬼醋旦。 笑死恒水,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的饲齐。 我是一名探鬼主播钉凌,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼捂人!你這毒婦竟也來了御雕?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤滥搭,失蹤者是張志新(化名)和其女友劉穎酸纲,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體论熙,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡福青,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了脓诡。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片无午。...
    茶點故事閱讀 40,872評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖祝谚,靈堂內(nèi)的尸體忽然破棺而出宪迟,到底是詐尸還是另有隱情,我是刑警寧澤交惯,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布次泽,位于F島的核電站穿仪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏意荤。R本人自食惡果不足惜啊片,卻給世界環(huán)境...
    茶點故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望玖像。 院中可真熱鬧紫谷,春花似錦、人聲如沸捐寥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽握恳。三九已至瞒窒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間乡洼,已是汗流浹背崇裁。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留就珠,地道東北人寇壳。 一個月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像妻怎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子泞歉,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,876評論 2 361

推薦閱讀更多精彩內(nèi)容