關於跨域,你須要知道的

前言:跨域對於大多數開發人員並不陌生,可是當咱們遇到跨域的時候,大部分前端開發者都會說出一種解決方案:讓服務端設置一下參數就好了。那爲何服務端設置了這些參數就能解決跨域問題呢?除了服務端解決,還有沒有其餘的解決方案呢?本文會具體分析一下產生跨域的緣由以及其餘的解決跨域的方案。javascript

1、爲何會跨域

一、什麼是跨域
假若有一個頁面A(url:https://www.a.com),頁面中有一個接口請求:https://www.b.com/getData;當咱們在瀏覽器中發送這個請求的時候,瀏覽器就會報錯,錯誤信息大概以下:前端

Access to XMLHttpRequest at 'https://www.b.com/' from origin 'https://www.a.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.java

看到這個錯誤你們就知道了產生了跨域的問題。
二、跨域的緣由
知道了什麼是跨域,那爲何會產生跨域的問題呢?
瀏覽器爲了保護用戶的信息安全提出了同源策略(注:這裏須要特別注意一下是在瀏覽器中才會有同源策略的限制):node

  • 協議相同
  • 域名相同
  • 端口相同

只有同時知足以上三個條件,咱們就說兩個url是同源的;因此,非同源之間就會產生跨域的問題。那既然知道了跨域產生的緣由,接下來咱們看一下幾種經常使用的解決跨域的方案。固然,也有其餘的方案,這裏就很少說了,你們能夠自行查詢一下。web

2、解決跨域的幾種方案

一、JSONP
jsonp全稱是json with padding,這是一種比較"古老"的解決跨域的方案,在那個年代,對於一些簡單的get請求,咱們能夠經過這種方式解決;可是其餘的一些複雜的請求(好比post),就須要用一些現代的方法解決了,那爲何jsonp不能發post請求呢?這要看一下jsonp解決跨域的原理:json

雖然瀏覽器有同源策略的限制,可是script標籤卻不受同源策略的限制,也就是經過script咱們能夠向不一樣的源發出請求。跨域

因爲script經過src發出的是get請求,因此jsonp的方式不不能解決post請求的跨域的。瀏覽器

// 客戶端代碼
function doJSONPRequestClickHandler() {
    let script = document.createElement('script');
    script.src = 'http://www.b.com/jsonp?callback=handleCallback';
    document.body.appendChild(script);
}
// 回調
let handleCallback = function(res) {
    console.log(res);
}
複製代碼

jsonp最關鍵的點就是http://www.b.com/jsonp?callback=handleCallback後面的callback參數,服務端接收到請求以後要處理這個參數:安全

// 服務端用nodejs
app.get('/jsonp', (req, res) => {
    let cb = req.query.callback;
    res.send(cb + '("jsonp跨域成功")');
});
複製代碼

當瀏覽器接收到服務端的響應也就是成功加載了js,就會當即執行handleCallback('jsonp跨域成功');
以上就是jsonp跨域的原理。
二、代理
使用代理的方式解決跨域的原理也很好理解:同源策略只是在瀏覽器中限制的,離開了瀏覽器環境是不受同源策略的限制的,因此經過代理的方式,將咱們的接口請求先發到同源的代理,而後再經過代理服務器轉發到目的服務器。
下面是經過nodejs中間件代理的方式解決跨域:服務器

const http = require('http');
const httpProxy = require('http-proxy');

const proxy = httpProxy.createProxyServer();

http.createServer((request, response) => {
    proxy.web(request, response, {
        target: 'https://www.b.com',
        changeOrigin: true,
    });
    proxy.on('error', err => {
        console.log(err);
    });
}).listen(8081);
複製代碼

三、CORS
文章剛開始講到的「讓服務端設置一下參數」就是經過CORS的方式解決跨域的,那麼什麼是CORS呢?
CORS就是跨源資源共享,雖然瀏覽器有同源策略的限制,可是瀏覽器給咱們開了一個「後門」,瀏覽器是容許發送跨域請求的,可是須要服務端配合在響應頭中設置一些特定的response header:

  • Access-Control-Allow-Origin: | *
  • Access-Control-Allow-Methods: [, ]*
  • Access-Control-Allow-Headers: [, ]*
  • Access-Control-Allow-Credentials: true
  • Access-Control-Allow-Origin

這個值是告訴客戶端容許的源是哪些,能夠設置爲特定的一個源或者*,當設置爲的時候容許全部的源跨域請求,這個設置爲的時候要很是當心;

  • Access-Control-Allow-Methods

它告訴客戶端容許跨域請求的方法是什麼,好比GET,POST,PUT等,能夠設置多個

  • Access-Control-Allow-Headers

若是請求頭中有一些自定義的請求頭,就須要設置這個屬性了,能夠設置多個

  • Access-Control-Allow-Credentials

當咱們的請求中須要帶一些cookie信息的時候,須要設置它的值爲true,須要注意一點,若是要使用這個屬性,那麼 Access-Control-Allow-Origin的值不能設置爲*。
CORS的設置以下:

app.post('/saveData', (req,res) => {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'POST');
    res.header('Access-Control-Allow-Headers', 'custom');
    console.log(req.body.name);
    res.send('接到了數據' + req.body.name);
});
複製代碼

三、總結

以上介紹了什麼是跨域,以及產生跨域的緣由;產生跨域時的幾種解決方案:jsonp、代理、cors...;經過以上的介紹,以後咱們再遇到跨域的問題的時候再也不只會說「讓服務端設置一下參數就好了」,可以明白爲何要服務端設置。 對於其餘的一些解決跨域的方案,本文中沒有說起,你們感興趣能夠本身研究一下,好比經過websocket、iframe等方式。

相關文章
相關標籤/搜索