天天看點

同源與跨域、JSONP(函數封裝)、CORS同源政策跨域問題

文章目錄

  • 同源政策
  • 跨域問題
    • JSONP
    • CORS

同源政策

Ajax請求限制:

Ajax 隻能向自己的伺服器發送請求。同源政策是浏覽器的一個安全功能,不同源的用戶端腳本在沒有明确授權的情況下,不能讀寫對方資源。

  • 比如現在有一個A網站、有一個B網站,A網站中的 HTML 檔案隻能向A網站伺服器中發送 Ajax 請求,B網站中的 HTML 檔案隻能向 B 網站中發送 Ajax 請求,但是 A 網站是不能向 B 網站發送 Ajax請求的,同理,B 網站也不能向 A 網站發送 Ajax請求。

同源:

如果兩個頁面擁有相同的協定、域名和端口,那麼這兩個頁面就屬于同一個源,其中隻要有一個不相同,就是不同源。

http://www.example.com/dir/page.html

  • http://www.example.com/dir2/other.html:同源
  • http://example.com/dir/other.html:不同源(域名不同)
  • http://v2.www.example.com/dir/other.html:不同源(域名不同)
  • http://www.example.com:81/dir/other.html:不同源(端口不同)
  • https://www.example.com/dir/page.html:不同源(協定不同)

同源政策的目的:

  • 同源政策是為了保證使用者資訊的安全,防止惡意的網站竊取資料。最初的同源政策是指 A 網站在用戶端設定的 Cookie,B網站是不能通路的。
  • 随着網際網路的發展,同源政策也越來越嚴格,在不同源的情況下,其中有一項規定就是無法向非同源位址發送Ajax 請求,如果請求,浏覽器就會報錯。

不受同源政策限制:

  • 頁面中的連結,重定向以及表單送出是不會受到同源政策限制的
  • 跨域資源的引入是可以的。但是js不能讀寫加載的内容。如嵌入到頁面中的

    <script src="..."></script>

    <img>

    <link>

    <iframe>

跨域問題

跨域:隻要協定、域名、端口号有一個不同就是跨域

跨域的原因:

跨域問題 來源于 JavaScript的同源政策,即隻有 協定+主機名+端口号(如存在)相同,則允許互相通路。為了防止某域名下的接口被其他域名下的網頁非法調用,是浏覽器對JavaScript施加的安全限制。也就是說JavaScript隻能通路和操作自己域下的資源,不能通路和操作其他域下的資源。跨域問題是針對 JS 和 Ajax 的, html 本身沒有跨域問題,比如a标簽、script标簽、甚至form标簽(可以直接跨域發送資料并接收資料) 等

解決跨域問題:

  • JSONP:利用script标簽可跨域的特點,在跨域腳本中可以直接回調目前腳本的函數。
  • CORS:伺服器設定HTTP響應頭中Access-Control-Allow-Origin值,解除跨域限制。
    • 注意:這兩個跨域方案都存在一個緻命的缺陷,嚴重依賴後端的協助。
  • 反向代理(Reverse Proxy):前端獨立就能解決的跨域方案:
指以 代理伺服器 來接受internet上的連接配接請求,然後将請求轉發給内部網絡上的伺服器,并将從伺服器上得到的結果傳回給internet上請求連接配接的用戶端,此時代理伺服器對外就表現為一個反向代理伺服器。

JSONP

使用 JSONP 解決

jsonp 是 JSON with padding(填充式 JSON 或參數式 JSON)的簡寫,它 不屬于 Ajax 請求,但它可以 模拟 Ajax 請求

JSONP 由兩部分組成:回調函數和資料

  • 回調函數是當響應到來時應該在頁面中調用的函數。回調函數的名字一般是在請求中指定的。
  • 資料就是傳入回調函數中的 JSON 資料。

解決方法:

簡單了解:在伺服器端将json資料作為函數參數,填充到函數當中,在用戶端中調用函數進而對資料進行處理

同源與跨域、JSONP(函數封裝)、CORS同源政策跨域問題

JSONP實作跨域請求的原理簡單的說,就是動态建立

<script>

标簽,然後利用

<script>

的 src 不受同源政策限制來跨域擷取資料。

JSONP的優缺點:

優點:

  • 不像XMLHttpRequest對象實作的Ajax請求那樣受到同源政策的限制
  • 相容性更好,在更加古老的浏覽器中都可以運作,不需要XMLHttpRequest或ActiveX的支援
  • 并且在請求完畢後可以通過調用callback的方式回傳結果

缺點:

  • 隻支援GET請求而不支援POST等其它類型的HTTP請求
  • 隻支援跨域HTTP請求這種情況,不能解決不同域的兩個頁面之間如何進行JavaScript調用的問題

JSONP代碼優化:

  1. 用戶端需要将函數名稱傳遞到伺服器端
  2. 将 script 請求的發送變成動态請求
  3. 封裝 jsonp 函數,友善請求發送
  4. 伺服器端代碼優化之res.jsonp 方法

JSONP函數封裝:

function jsonp (options) {
    // 動态建立script标簽
    var script = document.createElement('script');
    // 拼接字元串的變量
    var params = '';
    for (var attr in options.data) {
        params += '&' + attr + '=' + options.data[attr];
    }
    // myJsonp0124741
    var fnName = 'myJsonp' + Math.random().toString().replace('.', '');
    // 将它變成全局函數
    window[fnName] = options.success;
    // 為script标簽添加src屬性
    script.src = options.url + '?callback=' + fnName + params;
    // 将script标簽追加到頁面中
    document.body.appendChild(script);
    // 為script标簽添加onload事件
    script.onload = function () {
        document.body.removeChild(script);
    }
}
           

使用:

// 擷取按鈕
var btn1 = document.getElementById('btn1');
var btn2 = document.getElementById('btn2');
// 為按鈕添加點選事件
btn1.onclick = function () {
    jsonp({
        // 請求位址
        url: 'http://localhost:3001/better',
        data: {
            name: 'lisi',
            age: 30
        },
        success: function (data) {
            console.log(123)
            console.log(data)
        }
    })
}
btn2.onclick = function () {
    jsonp({
        // 請求位址
        url: 'http://localhost:3001/better',
        success: function (data) {
            console.log(456789)
            console.log(data)
        }
    })
}
           

CORS

使用CORS解決

CORS:全稱為 Cross-origin resource sharing,即跨域資源共享,它允許浏覽器向跨域伺服器發送 Ajax 請求,克服了 Ajax 隻能同源使用的限制。
同源與跨域、JSONP(函數封裝)、CORS同源政策跨域問題
//設定伺服器的響應頭資訊,實作跨域
res.setHeader("Access-Control-Allow-Origin", "*");  /* 星号表示所有的域都可以接受, */
           

Express架構中跨域的實作:

  1. 安裝跨域子產品:文法:

    npm install cors

  2. 在app.js檔案中引入cors子產品:

    var cors = require('cors')

  3. 使用跨域子產品(在app.js檔案中) :

    app.use(cors());

繼續閱讀