Web跨域分析與解決
阿新 • • 發佈:2022-04-22
前言
本片章敘述一下跨域問題,原來業務上也有碰到過此類問題,都是搜尋下答案先處理問題,只知如何解決但不知深原。
凡事多問個為什麼嘛~這已經是兩位前輩對我的深刻教誨了,深記於心。
多問:為什麼?
一.跨域問題的由來
二.怎麼就算跨域(同源的定義)
三.常見跨域解決方法
四.總結
一.跨域問題的由來
為什麼會產生這樣一個問題,擺在我們面前呢??
理解跨域,首先必須要了解同源策略。同源策略是瀏覽器上為安全性考慮實施的非常重要的安全策略。
為了防止某些文件或指令碼載入別的域下的未知內容造成洩露隱私,破壞系統等安全行為,
哦~說的很有道理,但腦子中沒有什麼體會認知吧?那咱們換個角度來說這個問題
假設沒有同源, 網際網路世界是什麼樣?
1.連結跳轉導致的問題.
沒有同源,a.com可以擁有對這個頁面完全的控制權. 攔截表單,捕獲資料,將賬號密碼上傳到a.com等等.
2.ajax請求, 要啥就有啥.
你登入jd.com產生了登陸cookie;
然後開啟a.com, a.com通過ajax 請求
這時候因為你登陸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等),來限制哪些域的請求和哪些請求型別可以接受。
可以在程式碼裡寫,也可以寫在伺服器配置檔案裡。
先解釋下有什麼配置,不用全寫,按需選取配置即可
實現ajax跨域訪問
配置可以在程式碼裡,
也可以寫在伺服器配置檔案(apache,nginx)裡。
[plain]
- 1)php程式碼
- header('Access-Control-Allow-Origin:*'); // 指定允許其他域名訪問
- header('Access-Control-Allow-Methods:POST'); // 響應型別
- header('Access-Control-Allow-Credentials:true'); //允許客戶端傳輸cookie
- 2) Nginx
- add_header 'Access-Control-Allow-Origin' '*';
- add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
- add_header 'Access-Control-Allow-Credentials' "true";
- 3) Apache
- Header set Access-Control-Allow-Origin www.a.com
- (開啟Credentials與Methods方式暫時報錯,待嘗試)
- /**
- * yii2 行為方法,自動執行開啟跨域@inheritdoc
- */
- public behaviors()
- {
- return [
- 'corsFilter' => [
- 'class' => \yii\filters\Cors::className(),
- 'cors' => [
- 'Origin''http://a.com''http://b.com'],//多域名設定
- 'Access-Control-Allow-Credentials' => true,
- ]
- ],
- ];
- }
- <!-- 前臺跨域程式碼格式 -->
- $.ajax({
- type: 'POST',
- url: 'http://www.b.com' ,
- data: {id:1} ,
- dataType: 'json',
- xhrFields: {withCredentials: 'true'},
- success:function(){alert(121);}
- });
- $origin = isset($_SERVER['HTTP_ORIGIN'])? $_SERVER['HTTP_ORIGIN'] : '';
- $allow_origin = array( 'http://client1.runoob.com', 'http://client2.runoob.com' );
- if(in_array($origin, $allow_origin)){header('Access-Control-Allow-Origin:'.$origin); }
- if ($http_origin ~ <允許的域(正則匹配)>) { add_header 'Access-Control-Allow-Origin'"$http_origin";
- if ($request_method = "OPTIONS") {...}
- }
搜尋
複製