介紹什麼是同源和什麼是跨域,以及三種解決跨域問題的路徑

橘子y發表於2020-11-16

 

什麼是同源?什麼是跨域?

客戶端向伺服器傳送請求的時候,如果協議,域名(IP)和埠都一樣,則稱為同源,但凡有一個不一樣則跨域,跨域請求預設受到瀏覽器的安全策略的限制,瀏覽器會給出相應的錯誤資訊,對於客戶端而言意味著請求失敗

  • 同源和跨域是瀏覽器的行為--瀏覽器安全機制

  • 請求要麼同源要麼跨域:不同源則跨域

  • 所謂同源就是指請求的源和對應的響應伺服器:協議一致,IP(域名)一致,埠一致

  • 影響範圍

    ajax 請求資料會受到影響,但是 html 程式碼中,二次請求檔案,比如圖片 img src, 或者 script src 這些不會受到限制

客戶端跨域

  • 我想通過遠端介面獲取天氣資訊

  • 找到介面:http://api.map.baidu.com/telematics/v3/weather?location=北京&output=json&ak=E4805d16520de693a3fe707cdc962045

  • 傳送請求,獲取到天氣資料

    $.ajax({
        type: 'get',
        url: 'http://api.map.baidu.com/telematics/v3/weather',
        data: {
            ak: 'zVo5SStav7IUiVON0kuCogecm87lonOj',
            location: '廣州',
            output: 'json'
        },
        success: function (result) {
            console.log(result.results[0].weather_data)
        }
    })

     

  • 跨域錯誤資訊

        

  •  

    錯誤資訊說明: 通過非同步方式,從源http://127.0.0.1:5500向http://api.baidu...傳送請求被CORS策略阻止了,不允許進行跨域請求

     

    解決跨域

1.第一種 在伺服器設定 ( Access-Control-Allow-Origin: *)(常用)

  • CROS 資料伺服器新增響應頭 Access-Control-Allow-Origin: *
  • 星號表示所有域名,也可用指定域名代替星號

2.第二種 Proxy 代理 (常用)

Proxy 代理,網頁伺服器,同時負責轉發不同伺服器的資料

只從網頁伺服器請求資料,那麼網頁和資料來自同一伺服器,就不是跨域了

開發伺服器轉發代理配置步驟:

配置 vue.config.js

  1. 如何分辨哪些是資料請求?

    proxy 是一個物件

    物件裡面是鍵值對, 其中 key 是用來匹配資料請求的

    我們希望所有資料請求都能統一處理,無需重複宣告

    • 在所有資料請求的前面新增 /api 標識

    • 然後就可以被 '/api' 攔截

  2. 將請求轉向真實資料伺服器

    target 配置

代理解決跨域的根本在於伺服器之間通訊受跨域影響, 可以用跟頁面同域的伺服器作為中轉轉發, 避免跨域問題.

 

 

3.第一種jsonp解決方式(但是在現在的前端領域並不常見了)

  •  

    jsonp 利用 script 標籤不受跨域限制的特性,使用 script 標籤向資料伺服器請求一個 js檔案,資料伺服器會將資料動態生成一個 js 檔案響應

     

  • 在ajax中實現跨域請求

    在客戶端實現跨域請求就稱為客戶端跨域

    ajax中通過設定dataType為jsonp就可以實現客戶端跨域

    // 關鍵程式碼:第11行
    $.ajax({
        type: 'get',
        url: 'http://api.map.baidu.com/telematics/v3/weather',
        data: {
            ak: 'zVo5SStav7IUiVON0kuCogecm87lonOj',
            location: '廣州',
            output: 'json'
        },
        // 開戶跨域請求
        dataType: 'jsonp',
        success: function (result) {
            console.log(result.results[0].weather_data)
        }
    })

     

jsonp客戶端跨域的原理

1.客戶端跨域的本質是利用了script標籤的src屬性的天然跨域特性來實現
2.客戶端傳送請求的時候,傳遞一個客戶端存在的函式名稱到伺服器,如<script src='http://127.0.0.1:3000/getData?callback=fn' ></script>
3.伺服器中獲取資料,根據接收的函式名稱拼接成函式呼叫形式,如 res.end('fn({ "a": 1, "b" : 2 })')
4.通過script傳送的請求,返回值預設會以js語法進行解析,客戶端接收從伺服器返回的資料(如:fn({ "aa": 11, "bb" : 22 })),以js語法解析,恰巧客戶端有一個fn函式,完美
5.客戶端獲取到資料

 

 

客戶端

<script>
    function fun(data){
    console.log("data:",data)
}
</script>
// 傳送請求,傳入客戶端定義好的函式
<script src="http://127.0.0.1:3000/getUserList?callback=fun"></script>

伺服器端

// 1.引入http模組
const http = require('http')
// 讀取檔案需要fs模組
const fs = require('fs')
​
// 2.建立伺服器
const server = http.createServer()
​
// 3.新增伺服器的埠監聽
server.listen(3000, function () {
    console.log('伺服器開好了: http://127.0.0.1:3000')
})
​
server.on('request', function (req, res) {
    let url = req.url
    let fun = req.url.split('=')[1]
    console.log(fun)
let data = [{id:1,name:'jack'},{id:2,name:rose},{id:3,name:'tom'}]
    if (url.indexOf('/getUserList?') === 0) {
        fs.readFile(__dirname + "/data/users.json",'utf-8', function (err, data) {
            if (err) {
                res.end(`${fun}("404")`)
            } else {
                // 關鍵程式碼:伺服器獲取資料後,拼接資料和函式名稱,返回函式的呼叫形式
                res.end(`${fun}(${data})`)
            }
        })
    }else{
        res.end(`${fun}("404")`)
    }
})

結果

 

總結:
所謂jsonp跨域就是利用了script標籤的src屬性的天然跨域特性,
在傳送請求的時候,傳遞一個客戶端的函式名稱到伺服器端,
伺服器端獲取資料,根據接收的函式名稱拼接為函式呼叫的形式,
並返回到客戶端,客戶端獲取返回資料的之後,按js語法進行解析,客戶端就順利的獲取到資料了
只能發起get請求
可以理解的是,jsonp跨域嚴重的需要伺服器端的配合,在現在的前端領域並不常見了

 

 

 

 

 

相關文章