跨域一

要明白什么是跨域郎逃,先要了解什么是同源策略,它的含義是指:

A網(wǎng)頁設置的 Cookie豁护,B網(wǎng)頁不能打開哼凯,除非這兩個網(wǎng)頁"同源"。所謂"同源"指的是"三個相同"楚里。

  • 協(xié)議相同
  • 域名相同
  • 端口相同

例如我的個人網(wǎng)站:http://www.tuituibang.top
協(xié)議是http://断部,域名是 www.tuituibang.top,端口是80(默認端口可以省略)
http://www.tuituibang.top/other.html:同源
http://example.com/dir/other.html:不同源(域名不同)
http://v2.www.tuituibang.top/other.html:不同源(域名不同)
http://www.tuituibang.top:8080/other.html:不同源(端口不同)
https://www.tuituibang.top/other.html:不同源(協(xié)議不同)

為什么要有同源策略班缎,同源政策的目的蝴光,是為了保證用戶信息的安全,防止惡意的網(wǎng)站竊取數(shù)據(jù)达址。如果是非同源的網(wǎng)站蔑祟,則受到以下的限制:

  • Cookie、LocalStorage 和 IndexDB 無法讀取沉唠。
  • DOM 無法獲得疆虚。
  • AJAX 請求不能發(fā)送。
什么是跨域?跨域有幾種實現(xiàn)形式
一:降域

例如:
one.tuituibang.com設置:document.domain = 'tuituibang.com'
two.tuituibang.com設置:document.domain = 'tuituibang.com'
one.tuituibang.comtwo.tuituibang.com就可以通過降域來帶到跨域傳遞數(shù)據(jù)
注:
1.兩個網(wǎng)頁一級域名相同径簿,只是二級域名不同,才能進行降域
2.這種方法只適用于 Cookie 和 iframe 窗口罢屈,LocalStorage 和 IndexDB 無法通過這種方法,規(guī)避同源政策
3.降域這個方法還是避免使用牍帚,有一定的安全隱患

二:window.postMessage

如果兩個網(wǎng)頁不同源儡遮,就無法拿到對方的DOM乳蛾。典型的例子是iframe窗口和window.open方法打開的窗口暗赶,它們與父窗口無法通信。
HTML5為了解決這個問題肃叶,引入了一個全新的API:跨文檔通信 API(Cross-document messaging)蹂随。
這個API為window對象新增了一個window.postMessage方法,允許跨窗口通信因惭,不論這兩個窗口是否同源岳锁。
舉例:
父窗口http://aaa.com向子窗口http://bbb.com發(fā)消息,調(diào)用postMessage方法就可以了蹦魔。

var popup = window.open('http://bbb.com/', 'title');
popup.postMessage('Hello World!', 'http://bbb.com/');

postMessage方法的第一個參數(shù)是具體的信息內(nèi)容激率,第二個參數(shù)是接收消息的窗口的源(origin),即"協(xié)議 + 域名 + 端口"勿决。也可以設為*乒躺,表示不限制域名,向所有窗口發(fā)送低缩。

子窗口向父窗口發(fā)送消息的寫法類似:

window.opener.postMessage('Nice to see you', 'http://aaa.com/');

父窗口和子窗口都可以通過message事件嘉冒,監(jiān)聽對方的消息。

window.addEventListener('message', function(e) {
  console.log(e.data);
},false);

message事件的事件對象event咆繁,提供以下三個屬性讳推。

  • event.source:發(fā)送消息的窗口
  • event.origin: 消息發(fā)向的網(wǎng)址
  • event.data: 消息內(nèi)容

下面的例子是,子窗口通過event.source屬性引用父窗口玩般,然后發(fā)送消息银觅。

window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
   event.source.postMessage('Nice to see you!', '*');
}

event.origin屬性可以過濾不是發(fā)給本窗口的消息。

window.addEventListener('message', receiveMessage);
function receiveMessage(event) { 
  if (event.origin !== 'http://aaa.com/') return; 
  if (event.data === 'Hello World') { 
      event.source.postMessage('Hello', event.origin); 
  } 
  else { 
      console.log(event.data); 
  }
}
三:JSONP

JSONP是服務器與客戶端跨源通信的常用方法坏为。最大特點就是簡單適用设拟,老式瀏覽器全部支持,需要被跨域的網(wǎng)站服務端進行配合
例如:

function addScriptTag(src) { 
        var script = document.createElement('script');
        script.setAttribute("type","text/javascript"); 
        script.src = src; 
        document.body.appendChild(script);
}
window.onload = function () { 
        addScriptTag('http://example.com/ip?callback=foo');
}
function foo(data) { 
        console.log('Your public IP address is: ' + data.ip);
};

動態(tài)添加<script>標簽久脯,向服務器example.com發(fā)出請求纳胧。注意,該請求的查詢字符串有一個callback參數(shù)帘撰,用來指定回調(diào)函數(shù)的名字跑慕,這對于JSONP是必需的。

后臺的代碼:

foo({
  "ip": "8.8.8.8"
});

由于<script>元素請求的腳本,直接作為代碼運行核行。這時牢硅,只要瀏覽器定義了foo函數(shù),該函數(shù)就會立即調(diào)用芝雪。作為參數(shù)的JSON數(shù)據(jù)被視為JavaScript對象减余,而不是字符串,因此避免了使用JSON.parse的步驟惩系。

JSONP的優(yōu)點是:它不像XMLHttpRequest對象實現(xiàn)的Ajax請求那樣受到同源策略的限制位岔;它的兼容性更好,在更加古老的瀏覽器中都 可以運行堡牡,不需要XMLHttpRequest或ActiveX的支持抒抬;并且在請求完畢后可以通過調(diào)用callback的方式回傳結(jié)果。

JSONP的缺點則是:它只支持GET請求而不支持POST等其它類型的HTTP請求晤柄;它只支持跨域HTTP請求這種情況擦剑,不能解決不同域的兩個頁面之間如何進行JavaScript調(diào)用的問題。

四:CORS

CORS是跨源資源分享(Cross-Origin Resource Sharing)的縮寫芥颈。它是W3C標準惠勒,是跨源AJAX請求的根本解決方法。相比JSONP只能發(fā)GET請求爬坑,CORS允許任何類型的請求纠屋。

瀏覽器將CORS請求分成兩類:######

簡單請求(simple request)和非簡單請求(not-so-simple request)。
簡單請求:
(1) 請求方法是以下三種方法之一:

  • HEAD
  • GET
  • POST

(2)HTTP的頭信息不超出以下幾種字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三個值application/x-www-form-urlencoded妇垢、multipart/form-data巾遭、text/plain

凡是不同時滿足上面兩個條件,就屬于非簡單請求闯估。

下面是一個例子灼舍,瀏覽器發(fā)現(xiàn)這次跨源AJAX請求是簡單請求,就自動在頭信息之中涨薪,添加一個Origin字段骑素。

GET /cors HTTP/1.1
Origin: http://api.bob.com/
Host: api.alice.com
Accept-Language: en-USConnection: 
keep-aliveUser-Agent: Mozilla/5.0...

上面的頭信息中,Origin字段用來說明刚夺,本次請求來自哪個源(協(xié)議 + 域名 + 端口)献丑。服務器根據(jù)這個值,決定是否同意這次請求侠姑。
如果Origin指定的源创橄,不在許可范圍內(nèi),服務器會返回一個正常的HTTP回應莽红。瀏覽器發(fā)現(xiàn)妥畏,這個回應的頭信息沒有包含Access-Control-Allow-Origin字段(詳見下文)邦邦,就知道出錯了,從而拋出一個錯誤醉蚁,被XMLHttpRequest的onerror回調(diào)函數(shù)捕獲燃辖。注意,這種錯誤無法通過狀態(tài)碼識別网棍,因為HTTP回應的狀態(tài)碼有可能是200黔龟。
如果Origin指定的域名在許可范圍內(nèi),服務器返回的響應滥玷,會多出幾個頭信息字段氏身。

Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8

上面的頭信息之中,有三個與CORS請求相關的字段罗捎,都以Access-Control-開頭观谦。
(1)Access-Control-Allow-Origin
該字段是必須的拉盾。它的值要么是請求時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字段的值。

要使用CORS舷暮,我們需要了解前端和服務器端的使用方法态罪。
1、 前端
以前我們使用Ajax下面,代碼類似于如下的方式:

var xhr = new XMLHttpRequest();  
xhr.open("GET", "/index.html", true);  
xhr.send();  

這里的“/index.html”是本域的相對路徑复颈。
如果我們要使用CORS,相關Ajax代碼可能如下所示:

var xhr = new XMLHttpRequest();  
xhr.open("GET", "http://www.tuituibang.top/index.html", true);  
xhr.send();  

請注意:
代碼與之前的區(qū)別就在于相對路徑換成了其他域的絕對路徑沥割,也就是你要跨域訪問的接口地址耗啦。
提供瀏覽器回退功能檢測和支持,避免瀏覽器不支持的情況机杜。

function createCORSRequest(method, url) {  
  var xhr = new XMLHttpRequest();  
  if ("withCredentials" in xhr) {  
    // 此時即支持CORS的情況  
    // 檢查XMLHttpRequest對象是否有“withCredentials”屬性  
    // “withCredentials”僅存在于XMLHTTPRequest2對象里  
    xhr.open(method, url, true);  
   
  } else if (typeof!= "undefined") {  
    // 否則檢查是否支持XDomainRequest帜讲,IE8和IE9支持  
    // XDomainRequest僅存在于IE中,是IE用于支持CORS請求的方式  
    xhr = new XDomainRequest();  
    xhr.open(method, url);  
   
  } else {  
    // 否則椒拗,瀏覽器不支持CORS  
    xhr = null;    
  }  
  return xhr;  
}  
   
var xhr = createCORSRequest('GET', url);  
if (!xhr) {  
  throw new Error('CORS not supported');  
}  

服務器端對于CORS的支持似将,主要就是通過設置Access-Control-Allow-Origin來進行的。如果瀏覽器檢測到相應的設置蚀苛,就可以允許Ajax進行跨域的訪問在验。
Apache:Apache需要使用mod_headers模塊來激活HTTP頭的設置,它默認是激活的堵未。你只需要在Apache配置文件的<Directory>, <Location>, <Files>或<VirtualHost>的配置里加入以下內(nèi)容即可:

Header set Access-Control-Allow-Origin *  

后臺PHP:

Access-Control-Allow-Origin: http://www.tuituibang.top

下面的設置使得只有http://www.tuituibang.top這個域才能跨域訪問服務器的API腋舌。

目前只涉及到簡單請求,非簡單請求后續(xù)補充

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渗蟹,一起剝皮案震驚了整個濱河市块饺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌雌芽,老刑警劉巖授艰,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異膘怕,居然都是意外死亡想诅,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門岛心,熙熙樓的掌柜王于貴愁眉苦臉地迎上來来破,“玉大人,你說我怎么就攤上這事忘古∨墙” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵髓堪,是天一觀的道長送朱。 經(jīng)常有香客問我娘荡,道長,這世上最難降的妖魔是什么驶沼? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任炮沐,我火速辦了婚禮,結(jié)果婚禮上回怜,老公的妹妹穿的比我還像新娘大年。我一直安慰自己,他們只是感情好玉雾,可當我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布翔试。 她就那樣靜靜地躺著,像睡著了一般复旬。 火紅的嫁衣襯著肌膚如雪垦缅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天驹碍,我揣著相機與錄音壁涎,去河邊找鬼。 笑死幸冻,一個胖子當著我的面吹牛粹庞,可吹牛的內(nèi)容都是我干的咳焚。 我是一名探鬼主播洽损,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼革半!你這毒婦竟也來了碑定?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤又官,失蹤者是張志新(化名)和其女友劉穎延刘,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體六敬,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡碘赖,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了外构。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片普泡。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖审编,靈堂內(nèi)的尸體忽然破棺而出撼班,到底是詐尸還是另有隱情,我是刑警寧澤垒酬,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布砰嘁,位于F島的核電站件炉,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏矮湘。R本人自食惡果不足惜斟冕,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缅阳。 院中可真熱鬧宫静,春花似錦、人聲如沸券时。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橘洞。三九已至捌袜,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間炸枣,已是汗流浹背虏等。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留适肠,地道東北人霍衫。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像侯养,于是被迫代替她去往敵國和親敦跌。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,500評論 2 359

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

  • 題目1.什么是同源策略? 同源策略(Same origin Policy): 瀏覽器出于安全方面的考慮逛揩,只允許與本...
    FLYSASA閱讀 1,727評論 0 6
  • 什么是跨域 跨域柠傍,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的辩稽,是瀏覽器對JavaScript實...
    Yaoxue9閱讀 1,301評論 0 6
  • 什么是跨域 跨域惧笛,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的逞泄,是瀏覽器對JavaScript實...
    他方l閱讀 1,064評論 0 2
  • 什么是跨域 跨域患整,是指瀏覽器不能執(zhí)行其他網(wǎng)站的腳本。它是由瀏覽器的同源策略造成的喷众,是瀏覽器對JavaScript實...
    HeroXin閱讀 837評論 0 4
  • 參考:瀏覽器的同源策略瀏覽器同源政策及其規(guī)避方法同源政策 什么是同源策略各谚? 同源策略限制了從同一個源加載的文檔或腳...
    DHFE閱讀 543評論 0 0