如何克服ajax跨域

背景

?最近做項目經(jīng)常碰到跨域的問題疗我,總在聯(lián)調(diào)中浪費了不少時間垮庐,當然若時間充裕的話银觅,跨域基本都是可以通jsonp來解決問題(get方式的請求),只是因為對接環(huán)境問題践宴,就打算在請求頭設置參數(shù)來解決跨域問題鲸匿。

跨域資源共享 CORS 原理

?CORS定義一種跨域訪問的機制,可以讓AJAX實現(xiàn)跨域訪問阻肩。CORS 允許一個域上的網(wǎng)絡應用向另一個域提交跨域 AJAX 請求带欢。實現(xiàn)此功能非常簡單,只需由服務器發(fā)送一個響應標頭即可。這種方案也是我們最長用的洪囤,也是比較簡單的徒坡。

例子如下:

JAVA后端代碼:

response.setHeader("Access-Control-Allow-Origin", "http://www.xxx.com");

response.setHeader("Access-Control-Allow-Credentials", "true");

(1)Access-Control-Allow-Origin

表示接受任意域名的請求,如果是多個域名中間用','隔開瘤缩,如果是 * 表示允許任何域名

(2)Access-Control-Allow-Credentials

該字段可選喇完。它的值是一個布爾值,表示是否允許發(fā)送Cookie剥啤。默認情況下锦溪,Cookie不包括在CORS請求之中。設為true府怯,即表示服務器明確許可刻诊,Cookie可以包含在請求中,一起發(fā)給服務器牺丙。這個值也只能設為true则涯,如果服務器不要瀏覽器發(fā)送Cookie,刪除該字段即可冲簿。

(3)Access-Control-Expose-Headers

該字段可選粟判。CORS請求時,XMLHttpRequest對象的getResponseHeader()方法只能拿到6個基本字段:Cache-Control峦剔、Content-Language档礁、Content-Type、Expires吝沫、Last-Modified呻澜、Pragma。如果想拿到其他字段惨险,就必須在Access-Control-Expose-Headers里面指定羹幸。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值

(4)Access-Control-Allow-Credentials

CORS請求默認不發(fā)送Cookie和HTTP認證信息辫愉。如果要把Cookie發(fā)到服務器睹欲,一方面要服務器同意,指定Access-Control-Allow-Credentials字段一屋。另外發(fā)送請求方需要varxhr=newXMLHttpRequest();? ?xhr.withCredentials=true; 否則,即使服務器同意發(fā)送Cookie袋哼,瀏覽器也不會發(fā)送冀墨。或者涛贯,服務器要求設置Cookie诽嘉,瀏覽器也不會處理。但是,如果省略withCredentials設置虫腋,有的瀏覽器還是會一起發(fā)送Cookie骄酗。這時,可以顯式關閉withCredentials悦冀。

然而我們經(jīng)常設置這樣的選項趋翻,還是會在瀏覽器彈出:XMLHttpRequest cannot load http:/www.xxx.com.Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin. 這樣的字眼,而且在post請求復現(xiàn)高盒蟆。

這個時候多是因為瀏覽器發(fā)送了有一個預檢請求踏烙,"預檢"請求用的請求方法是OPTIONS,表示這個請求是用來詢問的历等。頭信息里面讨惩,關鍵字段是Origin,表示請求來自哪個源寒屯。

在預檢請求會帶兩個參數(shù)

(1)Access-Control-Request-Method

該字段是必須的荐捻,用來列出瀏覽器的CORS請求會用到哪些HTTP方法,上例是PUT寡夹。

(2)Access-Control-Request-Headers

該字段是一個逗號分隔的字符串处面,指定瀏覽器CORS請求會額外發(fā)送的頭信息字段

服務器收到"預檢"請求以后,檢查了Origin要出、Access-Control-Request-Method和Access-Control-Request-Headers字段以后鸳君,確認允許跨源請求,就可以做出回應患蹂。

所以如果是post的請求獲取其他非簡單的請求的話或颊,我們可以嘗試在請求頭中加上

response.setHeader(Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");(注意,返回的是所有支持的方法传于,而不單是瀏覽器請求的那個方法囱挑。這是為了避免多次"預檢"請求。)

res.setHeader("Access-Control-Allow-Headers", "Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With,userId,token");

就能解決上述的即使加了請求頭允許跨域的域名以及Cookie的身份驗證沼溜,依舊出現(xiàn)跨域的問題平挑。

由于CORS請求和瀏覽器有關,所以在低版本IE或者其他的流量器如果不支持系草,該方式是行不通的通熄,這個時候就只能使用JsonP的方式來解決跨域。

JSONP解決跨域原理

JSONP(JSON with Padding)是JSON的一種”使用模式”找都,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題唇辨。由于同源策略,一般來說位于 server1.example.com 的網(wǎng)頁無法與不是 server1.example.com的服務器溝通能耻,而 HTML 的script元素是一個例外赏枚。利用 標簽<script>元素的這個開放策略亡驰,網(wǎng)頁可以得到從其他來源動態(tài)產(chǎn)生的 JSON 資料,而這種使用模式就是所謂的 JSONP饿幅。用 JSONP 抓到的資料并不是 JSON凡辱,而是任意的JavaScript,用 JavaScript 直譯器執(zhí)行而不是用 JSON 解析器解析栗恩。?元素的這個開放策略透乾,網(wǎng)頁可以得到從其他來源動態(tài)產(chǎn)生的 JSON 資料,而這種使用模式就是所謂的 JSONP摄凡。用 JSONP 抓到的資料并不是 JSON续徽,而是任意的JavaScript,用 JavaScript 直譯器執(zhí)行而不是用 JSON 解析器解析亲澡。

通俗的來講就是:JSONP的最基本的原理是:動態(tài)添加一個標簽钦扭,而script標簽的src屬性是沒有跨域的限制的。這樣說來床绪,這種跨域方式其實與ajax XmlHttpRequest協(xié)議無關了客情。標簽,而script標簽的src屬性是沒有跨域的限制的癞己。這樣說來膀斋,這種跨域方式其實與ajax XmlHttpRequest協(xié)議無關了。


下面是簡單的dome? 由于訪問本地沒有跨域痹雅,這里只是講解:


紅色框內(nèi)是一個ajax的跨域請求仰担,假設前端請求的是一個不在當前域地址,這個時候瀏覽器會出現(xiàn)跨域的錯誤提示绩社;

于是我們用,<script>標簽的特性來解決這問題:


這樣的話摔蓝,就能正常訪問跨域的請求接口了。

兩者相比:

Jsonp不會因為瀏覽器原因而不支持跨域愉耙,但是jsonp只是支持get方式的請求贮尉,所以兩者相比的話,因環(huán)境而定朴沿,并沒有誰好誰劣

?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末猜谚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子赌渣,更是在濱河造成了極大的恐慌魏铅,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件坚芜,死亡現(xiàn)場離奇詭異沦零,居然都是意外死亡,警方通過查閱死者的電腦和手機货岭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進店門路操,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人千贯,你說我怎么就攤上這事屯仗。” “怎么了搔谴?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵魁袜,是天一觀的道長。 經(jīng)常有香客問我敦第,道長峰弹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任芜果,我火速辦了婚禮鞠呈,結果婚禮上,老公的妹妹穿的比我還像新娘右钾。我一直安慰自己蚁吝,他們只是感情好,可當我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布舀射。 她就那樣靜靜地躺著窘茁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪脆烟。 梳的紋絲不亂的頭發(fā)上山林,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天,我揣著相機與錄音邢羔,去河邊找鬼驼抹。 笑死,一個胖子當著我的面吹牛张抄,可吹牛的內(nèi)容都是我干的砂蔽。 我是一名探鬼主播,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼署惯,長吁一口氣:“原來是場噩夢啊……” “哼左驾!你這毒婦竟也來了?” 一聲冷哼從身側響起极谊,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤诡右,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后轻猖,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體帆吻,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年咙边,在試婚紗的時候發(fā)現(xiàn)自己被綠了猜煮。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片次员。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖王带,靈堂內(nèi)的尸體忽然破棺而出淑蔚,到底是詐尸還是另有隱情,我是刑警寧澤愕撰,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布刹衫,位于F島的核電站,受9級特大地震影響搞挣,放射性物質發(fā)生泄漏带迟。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一囱桨、第九天 我趴在偏房一處隱蔽的房頂上張望仓犬。 院中可真熱鬧,春花似錦蝇摸、人聲如沸婶肩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽律歼。三九已至,卻和暖如春啡专,著一層夾襖步出監(jiān)牢的瞬間险毁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工们童, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留畔况,地道東北人。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓慧库,卻偏偏與公主長得像跷跪,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子齐板,可洞房花燭夜當晚...
    茶點故事閱讀 43,465評論 2 348

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