javaScript_跨域資源共享CORS

          要記錄好這個問題,首先需要描述清楚這個問題。
          有如下的一個場景:我們在實現一個系統中某個功能的時候,可能系統的某些模塊不在一個域名下。用戶中心模塊部署在user.xxx.com下,產品相關的功能部署在product.xxx.com下,在用戶中心的某些頁面,我們或許要請求產品功能模塊的功能,此時就會有問題出現。以Google Chrome(版本 45.0.2454.101 m)瀏覽器為例,當當前的頁面在A域名下,我們在頁面中構造了一個異步請求,我們需要調用位于B域名下的某個API,代碼片段如下:
          <script type="text/javascript">
              $(function() {
                  //當前頁面所在域名:http://localhost:9000/
                  //jQuery版本:jquery-1.11.3.min.js
                  $.ajax({
                      url : "http://localhost:9001/order/pindexpost",
                      type : "POST",
                      dataType : 'json',
                      success : function(data) {
                          alert(data);
                      }
                  });
              });
          </script>
          但是請求之后,瀏覽器控制臺給出了如下的錯誤信息

          那么這就是標題中所提到的跨域資源共享CORS問題了。我們把這個概念細化一下,首先,為什么會有CORS?簡單點理解就是出于安全考慮,瀏覽器都遵循一個叫同源策略的東西,他約束瀏覽器說“不是你的東西,你問人家要,人家默認不給你,除非人家同意給你”,基于這個策略,就有了跨域資源共享的問題,那么,怎么就叫跨域了呢?上面代碼中的域名不是一樣的嗎,都是指向本地的localhost啊。舉個栗子說明下

          http://www.aygfsteel.com:80,左邊是一個完整的請求,包含了協議,子域名等等若干部分,我們把它理解為域,但凡是在這個域下發生的請求,都無法直接訪問到其他域的資源
          • http://www.aygfsteel.com:80能訪問http://www.aygfsteel.com:81下的資源嗎?不行!
          • http://www.aygfsteel.com:80能訪問http://abc.blogjava.net:80下的資源嗎?不行!
          • http://www.aygfsteel.com:80能訪問http://www.aygfsteel.com:80下的資源嗎?不行!
          • http://www.aygfsteel.com:80能訪問http://域名對應的真實IP:80下的資源嗎?不行!
          • http://www.aygfsteel.com:80能訪問http://www.xyz.net:80下的資源嗎?不行!
          域哪怕有一點點不一樣,一點點不一樣,一點點不一樣,都是不可以訪問的,那么問題來了,如何實現跨域呢? 目前有三種方案可以打破同源策略所帶來的限制,實現跨域請求。
          1. 使用JSONP。這種方案是使用HTML的script標簽來實現的,script標簽的src屬性不受同源策略約束,可以訪問任意站點的資源,但是,該方案有著自己的約束。首先,他只能發出GET請求,因為script標簽的初衷就是為了獲取js腳本,所以如果返回的數據內容不是js腳本的話,也不會成功?;谶@個約束,我們需要改造一下我們的請求:
             1 <script type="text/javascript">
             2     $(function () {
             3     //當前頁面所在域名:http://localhost:9000/
             4     // jQuery版本:jquery-1.11.3.min.js
             5         $.ajax({
             6             url: "http://localhost:9001/order/pindexpost",
             7             type: "POST", dataType: 'jsonp',
             8             jsonpCallback: "callback"
             9         });
            10     })
            11     ;
            12     function callback(result) {
            13         alert("suc:" + result);
            14     }
            15 </script> 
            剛才提到,JSONP方式是基于script標簽的,所以我們要對返回的數據做一些處理,使返回的數據是一段js腳本才可以。我們在客戶端預定義好callback函數,使得服務端返回數據的時候可以直接調用這個callback函數,服務端代碼片段如下:
            1 response().setContentType("application/javascript");
            2 return ok("callback(" + data + ")");
            要注明返回的格式,并且data的格式也要符合js的語法。其實說白了,JSONP就是請求目標數據,然后將目標數據和回調函數進行拼接,以javascript的形式返回給瀏覽器,之后瀏覽器執行的這個回調函數。
          2. 使用代理服務器。這個比較好理解,不過運維的成分多一些,設置一個代理服務器,根據請求API所在命名空間的不同,轉發到相應的域去,這樣一來就騙過了瀏覽器,讓瀏覽器以為所有的數據都來自一個域。
          3. 設置請求的相應頭。在目標API的響應頭中添加“Access-Control-Allow-Origin”,設置值為“*”,這就是讓服務器通知瀏覽器,說“我這個API的響應,是面向所有人的,*就代表這個意思啊”,但是,這也會帶來一個安全性的問題,所以你可以設置部分站點可以跨域訪問,比如Access-Control-Allow-Origin: http://www.aygfsteel.com/,但是這個響應頭存在一定的兼容問題,具體支持情況可以查看caniuse.com

          posted on 2015-11-26 16:46 都較瘦 閱讀(160) 評論(0)  編輯  收藏 所屬分類: JavaScript案例積累

          <2015年11月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          導航

          統計

          公告

          博客定位:囿于目前的水平,博客定位在記錄自己的學習心得和隨手的練習

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 宝山区| 松原市| 巩义市| 明星| 海兴县| 泾川县| 宜君县| 谷城县| 老河口市| 上高县| 苏尼特左旗| 都兰县| 石狮市| 太康县| 夏津县| 会宁县| 五大连池市| 古丈县| 正阳县| 东辽县| 玉环县| 尖扎县| 拜城县| 孝义市| 固安县| 边坝县| 宁海县| 宜兰县| 太白县| 克东县| 宁明县| 托里县| 阳信县| 西安市| 洮南市| 姚安县| 海淀区| 宜都市| 微山县| 电白县| 雅江县|