1. 程式人生 > >javascript跨域:什麼是跨域,如何跨域(轉載自小鬍子哥)

javascript跨域:什麼是跨域,如何跨域(轉載自小鬍子哥)

---恢復內容開始---

  無數次看到:Origin null is not allowed by Access-Control-Allow-Origin , 網路沒有讓你絕望,但是或許會讓你蛋疼,因為你找了半天沒看到一個比較實用的解決方案,亦或者水平不夠,別人寫的東西累贅沒看懂,抑或是。。。

  網上看到了一篇文章——跨域資源共享的10中方式,已經放在自己的家裡了O(∩_∩)O~

  跨域也是平時專案中比較讓人頭疼的一個玩意兒,上文只是簡要地提出了有哪些跨域方式,這裡呢,將向大家詳細說明,各種使用頻率比較高的跨域方式。

  什麼是跨域:

cross-domain solution

 (CDS) is a means of information assurance that provides the ability to manually or automatically access or transfer between two or more differing security domains.

  上面是從wiki上引用過來的。意思是:解決兩個安全域之間的資訊傳遞,這個就叫做CDS——跨域解決方案。首先解釋下怎麼樣的兩個域之間的資料傳輸需要跨越。

 

What [什麼是跨域]

  JavaScript出於安全方面的考慮,不允許跨域呼叫其他頁面的物件。但在安全限制的同時也給注入iframe或是ajax應用上帶來了不少麻煩。這裡把涉及到跨域的一些問題簡單地整理一下:

  首先什麼是跨域,簡單地理解就是因為JavaScript同源策略的限制,a.com 域名下的js無法操作b.com或是c.a.com域名下的物件。更詳細的說明可以看下錶:

URL 說明 是否允許通訊
http://www.a.com/a.js
http://www.a.com/b.js
同一域名下 允許
http://www.a.com/lab/a.js
http://www.a.com/script/b.js
同一域名下不同資料夾 允許
http://www.a.com:8000/a.js
http://www.a.com/b.js
同一域名,不同埠 不允許
http://www.a.com/a.js
https://www.a.com/b.js
同一域名,不同協議 不允許
http://www.a.com/a.js
http://70.32.92.74/b.js
域名和域名對應ip 不允許
http://www.a.com/a.js
http://script.a.com/b.js
主域相同,子域不同 不允許
http://www.a.com/a.js
http://a.com/b.js
同一域名,不同二級域名(同上) 不允許(cookie這種情況下也不允許訪問)
http://www.cnblogs.com/a.js
http://www.a.com/b.js
不同域名 不允許

 

same-origin policy [同源策略]

  在客戶端程式語言中,如javascript和ActionScript,同源策略是一個很重要的安全理念,它在保證資料的安全性方面有著重要的意義。同源策略規定跨域之間的指令碼是隔離的,一個域的指令碼不能訪問和操作另外一個域的絕大部分屬性和方法。

  那麼什麼叫相同域,什麼叫不同的域呢?當兩個域具有相同的協議(如http), 相同的埠(如80),相同的host(如www.example.org),那麼我們就可以認為它們是相同的域。比如http://www.example.org/和http://www.example.org/sub/是同域,而http://www.example.org, https://www.example.org, http://www.example.org:8080, http://sub.example.org中的任何兩個都將構成跨域。同源策略還應該對一些特殊情況做處理,比如限制file協議下指令碼的訪問許可權。本地的html檔案在瀏覽器中是通過file協議開啟的,如果指令碼能通過file協議訪問到硬碟上其它任意檔案,就會出現安全隱患,目前IE8還有這樣的隱患。

  受到同源策略的影響,跨域資源共享就會受到制約。但是隨著人們的實踐和瀏覽器的進步,目前在跨域請求的技巧上,有很多寶貴經驗的沉澱和積累。這裡我把跨域資源共享分成兩種,一種是單向的資料請求,還有一種是雙向的訊息通訊。

 

 JSONP(JSON with padding)是JSON的一種“使用模式”,它是非官方協議允許在伺服器端整合Script tags返回至客戶端,通過javascript callback的形式實現跨域訪問(這僅僅是JSONP簡單的實現形式)。

  P.S:

    1.樓主懂一點點php,所以DEMO中的後臺語言就用PHP來演示。

    2.為了方便測試,樓主弄了SAE和BAE。

 

Prelude [前奏]

  如果我們請求一個JSON資料:(SAE地址:http://qianduannotes.sinaapp.com/test/testData_1.json)

//一個簡單的json資料
{
    "name" : "靖鳴君",
    "sex"    : "男",
    "hobby": "女"
}

  報個什麼錯,大家應該知道了吧~ 

Origin null is not allowed by Access-Control-Allow-Origin

  先解釋下這個null是個什麼東東。很多人在測試的時候是在沒有諸如apache、IIS環境下執行的程式,也就是在本地執行,此時origin就是null,所有Access-Control-Allow-Origin這個東西不允許源null請求資料。當然如果你測試的時候在apache下執行,那這裡的null就會變成你的IP了~

 

Then [接著]

  JSONP,我們開始入題吧~ 

  先說說後臺返回個什麼東西:(SAE地址:http://qianduannotes.sinaapp.com/test/CDS_jsonp.json)

<?php
    $fun = $_GET["woo"];  //先假設woo對應的是 trigger ;
    $ctt = "靖鳴君";
    echo $fun . "(" . $ctt . ")";
?>

  後臺資料解析之後就是這樣的:

trigger(木子Vs立青)

  有人就要開始驚歎了,腫麼是 木子Vs立青 ,沒有引號包住??是的,沒有引號,當$ctt是一個json資料的時候,我們得到的結果就是:

trigger(JSON)

  然後用一些熟知的方法來解析這些JSON(下次會講解如何解析JSON)。

  說了半天還是沒講客戶端的操作,O(∩_∩)O~  不急不急。

<script type="text/javascript" src="http://qianduannotes.sinaapp.com/test/CDS_jsonp.php?woo=trigger"></script>
<script type="text/javascript">
function trigger(obj){
    //注:這裡只是隨便寫的一個函式,obj是為解析的。
    //obj = parse(obj);
    document.getElementById("container").innerHTML = obj;
  }
</script>

  習慣上jsonp請求時,會使用jsonp為引數,即jsonp=trigger,我覺得都無所謂啦,只要你用的爽就行。

  如果你想傳更多引數,那也是一樣的:

<script type="text/javascript" src="http://qianduannotes.sinaapp.com/test/CDS_jsonp.php?woo=trigger&a=va&b=vb&c=vc"></script>

 

Attention [注意事項]

  1.第一也是最重要的:JSONP不提供錯誤處理。如果動態插入的程式碼正常執行,你可以得到返回,但是如果失敗了,那麼什麼都不會發生。你無法獲得一個404的錯誤,也不能取消這個請求。

  2.另外一個重要的缺點是如果使用了不信任的服務會造成很大的安全隱患。

---恢復內容結束---