Stories

Detail Return Return

歸納跨域幾種解決方案 - Stories Detail

什麼是跨域?

**説起跨域,就要知道什麼是瀏覽器同源策略

**瀏覽器同源策略:必須是協議、域名、端口完全一致的才符合同源策略

**如果以上三項,有一項不同都涉及到跨域問題


為什麼瀏覽器要設置同源策略呢?

沒有同源策略限制的兩大危險場景
瀏覽器是從兩個方面去做這個同源策略的,一是針對接口的請求,二是針對Dom的查詢。

沒有同源策略限制的接口請求

沒有同源策略限制的接口請求通常是因為開發者或服務器管理員採取了特定的措施來繞過或放寬同源策略的限制。同源策略是瀏覽器的一個安全機制,它限制了一個網頁只能與其來源相同的網頁進行交互。這裏的“來源”指的是協議、域名和端口都必須相同。

通常涉及前端應用程序與後端服務之間的通信,特別是在這些服務位於不同源(即不同的協議、域名或端口)時。以下是一些可能導致跨域問題的常見場景:
1.前端應用和後端API位於不同域名:
假設你有一個前端Web應用(如https://frontend.example.com)與一個後端RESTful API(如https://api.example.net)進行通信。由於這兩個服務位於不同的域名,瀏覽器會應用同源策略,阻止前端應用直接訪問後端API。
2.前端開發環境使用localhost,而後端服務位於遠程服務器:
在開發過程中,前端應用可能運行在本地機器上(如http://localhost:3000),而後端API則部署在遠程服務器上(如https://dev-api.example.com)。由於端口和域名都不同,同源策略會阻止這種通信。
3.使用第三方API:
假設你的應用需要調用某個第三方API(如天氣API或支付API),而這些API位於與你的應用不同的源上。沒有適當的跨域設置,你的應用將無法與這些API通信。
4.使用iframe或popup窗口嵌入內容:
當你在一個頁面上使用iframe或JavaScript打開的popup窗口嵌入來自其他源的內容時,這些內容與主頁面之間可能會存在跨域問題。例如,你可能希望從iframe或popup中讀取或修改主頁面上的數據,但由於同源策略的限制,這通常是不允許的。
5.文件協議(file://)與HTTP/HTTPS之間的通信:
如果你在本地通過文件系統(如file:///path/to/your/app.html)直接打開HTML文件,並嘗試與HTTP或HTTPS服務器上的服務進行通信,這也會觸發跨域問題。
6.端口號不同:
即使域名相同,但如果端口號不同(如http://example.com與http://example.com:8080),也會觸發跨域問題。
7.協議不同:
HTTP和HTTPS被視為不同的源。如果你的前端應用使用HTTP,而你的後端API使用HTTPS,那麼它們之間的通信將受到同源策略的限制。
8.本地開發服務器與遠程測試環境之間的通信:
在開發過程中,開發者可能會將代碼部署到遠程測試環境進行測試,但前端應用可能仍在本地運行。這種配置也可能導致跨域問題。
為了解決這些問題,開發者可以採用一些技術來允許跨域請求,例如CORS(跨源資源共享)、JSONP(JSON with Padding)、使用代理服務器、或配置瀏覽器以允許跨域請求(通常僅用於開發環境)


跨域解決方案

**1、 通過jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域資源共享(CORS)
7、 nginx代理跨域
8、 nodejs中間件代理跨域
9、 WebSocket協議跨域**

JSONP跨域

jsonp的原理就是利用<script>標籤沒有跨域限制,通過<script>標籤src屬性,發送帶有callback參數的GET請求,服務端將接口返回數據拼湊到callback函數中,返回給瀏覽器,瀏覽器解析執行,從而前端拿到callback函數返回的數據。
jsonp 缺點是隻能發送 get 請求


1)原生JS實現:

 <script>
    var script = document.createElement('script');
    script.type = 'text/javascript';

    // 傳參一個回調函數名給後端,方便後端返回時執行這個在前端定義的回調函數
    script.src = 'http://www.domain2.com:8080/login?                              user=admin&callback=handleCallback';
    document.head.appendChild(script);

    // 回調執行函數
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>

服務端返回如下(返回時即執行全局函數):

handleCallback({"success": true, "user": "admin"})

2)jquery Ajax實現:

$.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // 請求方式為jsonp
    jsonpCallback: "handleCallback",  // 自定義回調函數名
    data: {}
});

3)Vue axios實現:

this.$http = axios;
this.$http.jsonp('http://www.domain2.com:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})

4)node.js實現:

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();

server.on('request', function(req, res) {
    var params = querystring.parse(req.url.split('?')[1]);
    var fn = params.callback;

    // jsonp返回設置
    res.writeHead(200, { 'Content-Type': 'text/javascript' });
    res.write(fn + '(' + JSON.stringify(params) + ')');

    res.end();
});

server.listen('8080');
console.log('Server is running at port 8080...');

CORS(跨域資源共享):

**CORS 是一種 W3C 規範,它定義了一種瀏覽器和服務器交互的方式來確定是否允許跨源請求。
服務器通過在響應頭中添加 Access-Control-Allow-Origin 等字段來告訴瀏覽器哪些源可以訪問其資源。
CORS 支持多種 HTTP 請求方法,如 GET、POST、PUT 等。**


1.)原生ajax

var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容

// 前端設置是否帶cookie
xhr.withCredentials = true;

xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');

xhr.onreadystatechange = function() {
    if (xhr.readyState == 4 && xhr.status == 200) {
        alert(xhr.responseText);
    }
};

2.)jQuery ajax

$.ajax({
    ...
   xhrFields: {
       withCredentials: true    // 前端設置是否帶cookie
   },
   crossDomain: true,   // 會讓請求頭中包含跨域的額外信息,但不會含cookie
    ...
});

3.)vue框架

a.) axios設置:
axios.defaults.withCredentials = true
b.) vue-resource設置:
Vue.http.options.credentials = true


服務器端代理:

這種方法通過在服務器端設置一個代理來轉發客户端的請求到目標服務器。
代理服務器與目標服務器之間的通信不受同源策略的限制,因為它們是服務器端之間的通信。
客户端向代理服務器發送請求,代理服務器將請求轉發給目標服務器,並將目標服務器的響應返回給客户端。


總結來説,沒有同源策略限制的接口請求通常是通過 JSONP、CORS、服務器端代理、反向代理或負載均衡器等方法來實現的。這些方法各有優缺點,開發者需要根據具體場景和需求來選擇合適的方法。

Add a new Comments

Some HTML is okay.