1. 程式人生 > 其它 >Web跨域分析與解決

Web跨域分析與解決

 前言 本片章敘述一下跨域問題,原來業務上也有碰到過此類問題,都是搜尋下答案先處理問題,只知如何解決但不知深原。 凡事多問個為什麼嘛~這已經是兩位前輩對我的深刻教誨了,深記於心。 多問:為什麼?   一.跨域問題的由來 二.怎麼就算跨域(同源的定義) 三.常見跨域解決方法 四.總結   一.跨域問題的由來 為什麼會產生這樣一個問題,擺在我們面前呢?? 理解跨域,首先必須要了解同源策略。同源策略是瀏覽器上為安全性考慮實施的非常重要的安全策略。 為了防止某些文件或指令碼載入別的域下的未知內容造成洩露隱私,破壞系統等安全行為,   哦~說的很有道理,但腦子中沒有什麼體會認知吧?那咱們換個角度來說這個問題 假設沒有同源, 網際網路世界是什麼樣? 1.連結跳轉導致的問題.
http://a.com
, 放一個連結到 icbc.com, 然後 window.open來開啟,window.open有個返回值控制代碼,
沒有同源,a.com可以擁有對這個頁面完全的控制權. 攔截表單,捕獲資料,將賬號密碼上傳到a.com等等.   2.ajax請求, 要啥就有啥. 你登入jd.com產生了登陸cookie; 然後開啟a.com, a.com通過ajax 請求http://jd.com 的使用者資訊介面, 這時候因為你登陸jd.com,所以a.com發起訪問jd.com自動帶上了jd的合法cookie,繞過jd的登陸驗證, 然後獲取到你京東的訂單list ,暱稱, 所有私密資訊返還給a.com.【是不是有點像CSRF?】   所以,為什麼需要同源策略,顯而易見,必須得限制跨域 (安全性和方便性是成反比的,同源策略提升了Web前端的安全性,但犧牲了Web拓展上的靈活性。所以,現代瀏覽器在安全性和可用性之間選擇了一個平衡點。在遵循同源策略的基礎上,選擇性地為同源策略“開放了後門”。例如img script style等標籤,都允許垮域引用資源,嚴格說這都是不符合同源要求的。)   二.怎麼就算跨域(同源的定義) 1995年, Netscape 公司在瀏覽器中引入同源策略/SOP(Same origin policy) 同domain(或ip),同埠,同協議視為同一個域,一個域內的指令碼僅僅具有本域內的許可權, 可以理解為本域指令碼只能讀寫本域內的資源,而無法訪問其它域的資源。這種安全限制稱為同源策略。   三.常見跨域解決方法 1.JSONP 在js中,我們直接用XMLHttpRequest請求不同域上的資料時,是不可以的。但是,在頁面上引入不同域上的js指令碼檔案卻是可以的,jsonp正是利用這個特性來實現的。 啥意思?正如前邊提到的,ajax訪問介面時受同源限制的,但是<script src="XXXX">是不受限制的,所以通過此方法避開同源限制。哈哈,本質是因為這樣啊,鑽了同源的漏網之魚。【通過script的src來載入,這也解釋了為什麼jsonp只支援get傳輸】 為啥還要有callback引數?因為需要一個代理函式做中間人來處理資料,這個引數成了約定的函式名了。 這樣jsonp的原理就很清楚了,通過script標籤引入一個js檔案,這個js檔案載入成功後會執行我們在url引數中指定的函式,並且會把我們需要的json資料作為引數傳入。所以jsonp是需要伺服器端的頁面進行相應的配合的。 如果你的頁面使用jquery,那麼通過它封裝的方法就能很方便的來進行jsonp操作了.原理是一樣的,只不過我們不需要手動的插入script標籤以及定義回掉函式。jquery會自動生成一個全域性函式來替換callback=?中的問號,之後獲取到資料後又會自動銷燬,實際上就是起一個臨時代理函式的作用。$.getJSON方法會自動判斷是否跨域,不跨域的話,就呼叫普通的ajax方法;跨域的話,則會以非同步載入js檔案的形式來呼叫jsonp的回撥函式。  
  2.CORS CORS(跨域資源共享,Cross-Origin Resource Sharing)是通過客戶端+服務端協作宣告的方式來確保請求安全的。 服務端會在HTTP請求頭中增加一系列HTTP請求引數(例如Access-Control-Allow-Origin等),來限制哪些域的請求和哪些請求型別可以接受。 可以在程式碼裡寫,也可以寫在伺服器配置檔案裡。   先解釋下有什麼配置,不用全寫,按需選取配置即可 Access-Control-Allow-Origin:指定授權訪問的域 Access-Control-Allow-Methods:授權請求的方法(GET,POST,PUT,DELETE,OPTIONS等)
Access-Control-Allow-Credentials 首部欄位用於預檢請求的響應,表明伺服器是否允許,credentials標誌設定為true的請求。 Access-Control-Max-Age:<delta-seconds> 首部欄位指明瞭預檢請求的響應的有效時間。delta-seconds 表示該響應在多少秒內有效。 Access-Control-Allow-Headers 首部欄位用於預檢請求的響應。其指明瞭實際請求中允許攜帶的首部欄位。 實現ajax跨域訪問 配置可以在程式碼裡, 也可以寫在伺服器配置檔案(apache,nginx)裡。 [plain]  view plain  copy  
  1. 1)php程式碼  
  2. header('Access-Control-Allow-Origin:*');  // 指定允許其他域名訪問    
  3. header('Access-Control-Allow-Methods:POST');  // 響應型別    
  4. header('Access-Control-Allow-Credentials:true');  //允許客戶端傳輸cookie  
  5.   
  6. 2) Nginx  
  7. add_header 'Access-Control-Allow-Origin' '*';  
  8. add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';  
  9. add_header 'Access-Control-Allow-Credentials' "true";  
  10.   
  11. 3) Apache  
  12. Header set Access-Control-Allow-Origin www.a.com  
  13. (開啟Credentials與Methods方式暫時報錯,待嘗試)  
  [php]  view plain  copy  
  1. /** 
  2.      * yii2 行為方法,自動執行開啟跨域@inheritdoc 
  3.      */  
  4.     public behaviors()  
  5.     {  
  6.   
  7.         return [  
  8.               
  9.             'corsFilter' => [  
  10.                 'class' => \yii\filters\Cors::className(),  
  11.                 'cors' => [  
  12.                     'Origin''http://a.com''http://b.com'],//多域名設定  
  13.                     'Access-Control-Allow-Credentials' => true,  
  14.                 ]  
  15.             ],  
  16.         ];  
  17.     }  
  18.       
[javascript]  view plain  copy  
  1. <!-- 前臺跨域程式碼格式 -->  
  2.  $.ajax({  
  3.      type: 'POST',  
  4.      url: 'http://www.b.com' ,  
  5.      data: {id:1} ,  
  6.      dataType: 'json',  
  7.      xhrFields: {withCredentials: 'true'},  
  8.      success:function(){alert(121);}  
  9. });  
效果演示 :以修改apache,nginx配置檔案的方法為例子 圖1.前臺跨域程式碼   圖2.觸發跨域後的提示   圖3.apache配置開啟跨域   圖4.nginx開啟跨域限制 圖5.再次呼叫跨域成功   正在上傳…重新上傳取消   c.iframe 本質www.a調用不了www.b下的東西,但是a可以iframe開啟一個b域名下的第三個頁面c,c與b是同域名讓c來呼叫b 所以ifame的本質就是,把a要呼叫b的程式碼邏輯寫到c裡邊,然後把c召喚出來即可,剩下的c來做也不涉及跨域. 這裡文章介紹的很好:iframe與主框架跨域相互訪問方法_傲雪星楓的部落格-CSDN部落格_iframe跨域 4、其它一些方式 WebSocket、伺服器代理、flash socket。這裡接不詳細敘述說了。   四.總結: 這麼一看,跨域限制還是很有必要的,安全。 但是為了方便,同源限制也開放了幾個可以跨域訪問的標籤<img><script><style>等 但是就是因為這個小缺口的開放不也是產生CSRF的可乘之機嘛 所以說,安全與便捷總是相對力點,就像原來聽說支付寶想推出一款掃物品就能付款的產品,出門不用帶錢包了,帶上這個設定的物體就行了,方便是方便了,但是多危險嗎丟了別人就隨便拿來支付了嗎。(不過後來也沒見阿里推出該產品哈哈)   五。注意點 1.關於Access-Control-Allow-Origin設定多域名問題 總不能給伺服器設定*吧太危險了,但是又想設定多域名,不能簡單的加逗號 比如:add_header 'Access-Control-Allow-Origin' 'www.a.com,www.b.com'; 是錯誤 因該怎麼做呢?加入邏輯程式碼,把它變數化。 [plain]  view plain  copy  
  1. $origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '';   
  2. $allow_origin = array( 'http://client1.runoob.com', 'http://client2.runoob.com' );  
  3. if(in_array($origin, $allow_origin)){header('Access-Control-Allow-Origin:'.$origin); }  
  4. if ($http_origin ~ <允許的域(正則匹配)>) { add_header 'Access-Control-Allow-Origin'"$http_origin";  
  5. if ($request_method = "OPTIONS") {...}  
  6. }  
2.關於Credentials設定問題 我們從上文知道,Credentials是開啟傳輸cookie的一個開關 但是注意: 1).首先:伺服器Access-Control-Allow-Origin【不能設定成*】 得設定成對應域名,否則無效!!! 2).其次,只在服務端設定開啟Access-Control-Allow-Credentials伺服器開啟不行, 還得客戶端開啟withCredentials=true,否則,即使伺服器同意傳送Cookie,瀏覽器也不會發送。或者,伺服器要求設定Cookie,瀏覽器也不會處理。   3.cors預檢請求問題 若http請求不是get,post,head,或者攜帶header頭過多,瀏覽器會先預檢請求(option(經測試確實存在兩次請求) 瀏覽器先詢問伺服器,當前網頁所在的域名是否在伺服器的許可名單之中,以及可以使用哪些HTTP動詞和頭資訊欄位。只有得到肯定答覆,瀏覽器才會發出正式的XMLHttpRequest請求,否則就報錯。     參考文章: 跨源資源共享(CORS) - HTTP | MDN iframe與主框架跨域相互訪問方法iframe與主框架跨域相互訪問方法_傲雪星楓的部落格-CSDN部落格_iframe跨域 js中幾種實用的跨域方法原理詳解js中幾種實用的跨域方法原理詳解 - 無雙 - 部落格園 前端跨域請求如何實現前端跨域請求如何實現? - 凱冰科技知識中心   本文地址:Web跨域分析與解決_時而寧靜的部落格-CSDN部落格_web跨域

搜尋

複製