欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡單易懂的JSONP和CORS跨域方案詳解

 更新時(shí)間:2022年10月11日 11:08:29   作者:mouche  
這篇文章主要為大家介紹了簡單易懂的JSONP和CORS跨域方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一、了解跨域

??何為跨域

  • 跨域并不是請求發(fā)不出去,請求能發(fā)出去,服務(wù)端能收到請求并正常返回結(jié)果,只是結(jié)果被瀏覽器攔截

那為什么攔截呢,我們應(yīng)該先了解一下什么是同源策略

  • MDN上的解釋:同源策略是一個(gè)重要的安全策略,它用于限制一個(gè)origin的文檔或者它加載的腳本如何能與另一個(gè)源的資源進(jìn)行交互。它能幫助阻隔惡意文檔,減少可能被攻擊的媒介

具體的限制(三限制):

  • 同源策略限制了來自不同源的 JavaScript 腳本對當(dāng)前DOM對象讀和寫的操作
  • 同源策略限制了來自不同源的站點(diǎn)讀取當(dāng)前的 Cookie、LocalStorage 等數(shù)據(jù)
  • 同源策略限制了通過 XMLHttpRequest等方式將站點(diǎn)的數(shù)據(jù)發(fā)送給不同源的站點(diǎn)

能使的標(biāo)簽(能跨域請求資源的標(biāo)簽):

  • <script src="..."></script>
  • <link rel="stylesheet" href="...">
  • 通過 <img>展示圖片
  • 通過 <video>和 <audio>播放的多媒體資源
  • 通過 <iframe>載入的任何資源

那你限制了我這么多東西,我要正常使用肯定要跨域嘍

??何為同源

如果兩個(gè) URL 的協(xié)議(Protocol),域名(domain),端口(port)都相同的話,則這兩個(gè) URL 是同源

  • 協(xié)議:定義了數(shù)據(jù)如何在計(jì)算機(jī)內(nèi)和之間進(jìn)行交換的規(guī)則的系統(tǒng)。例如:http,https
  • 域名:可以通過DNS解析為IP地址 (這里即使兩個(gè)不同的域名指向同一個(gè)IP地址,也是屬于不同源的)
  • 端口:http默認(rèn)使用80端口,https默認(rèn)使用443端口

舉個(gè)例子: 我們尋找跟掘金首頁:https://jbzj.cn/同源的URL

URL結(jié)果原因
http://jbzj.cn/不同源協(xié)議不同
https://jbzj.my.cn/不同源域名不同
https://jbzj.cn:3030/不同源端口不一樣(https默認(rèn)443端口)
https://jbzj.cn/user/2375390426313406同源只有路徑不一樣
https://jbzj.cn/post/7151609034699718692同源只有路徑不一樣

小結(jié):跨域的出現(xiàn)是因?yàn)闉g覽器的同源策略對不同協(xié)議,域名,端口的URL在DOM對象的讀寫,Cookie等數(shù)據(jù)的獲取,Ajax請求等方面有限制

二、跨域解決方案

JSONP(JSON with Padding)

  • 最容易記住也最容易理解的應(yīng)該就是JSONP了
  • 我們前面提到了<script src="..."></script>是可以跨域請求資源的,那么JSONP就是利用了這一點(diǎn)了

??簡單實(shí)現(xiàn)

  • 先上一個(gè)簡單的例子來理解思路
  • 在客戶端
  <script>
    function jsonp(){
      return new Promise((resolve, reject) => {
      //在全局定義一個(gè)doSomething的函數(shù)
        window['doSomething'] = function(data) {
          resolve(data); 
        }
      })
    }
    jsonp().then(res=>{
    //調(diào)用doSomething之后會(huì)在這里打印
      console.log(res)
    })
  </script>
  //使用script標(biāo)簽向后臺(tái)/test路徑發(fā)送參數(shù)callback為doSomething
  <script src="http://localhost:3000/test?callback=doSomething"></script>
  • 在服務(wù)端
app.get('/test',(req, res) => {
    //通過res.send()方法-將處理好的內(nèi)容,發(fā)送給客戶端
    let { callback } = req.query;
    //返回一個(gè)函數(shù)的執(zhí)行式doSomething(‘參數(shù)')
    res.send(`${callback}('這里是某車在使用簡單的JSONP')`)
})
  • 服務(wù)器返回doSomething('這里是某車在使用簡單的JSONP'),因?yàn)槲覀円呀?jīng)聲明過,所以客戶端會(huì)直接調(diào)用doSomething這個(gè)函數(shù),然后打印出了:這里是某車在使用簡單的JSONP

??流程圖

  • 全局聲明一個(gè)回調(diào)函數(shù)
  • 在<script>標(biāo)簽中,輸入U(xiǎn)RL,向服務(wù)器傳遞該函數(shù)名和參數(shù)(可以通過問號(hào)傳參:?callback=doSomething)
  • 服務(wù)器接收到請求后,需要進(jìn)行處理:把傳遞進(jìn)來的函數(shù)名和要返回的數(shù)據(jù)拼接為函數(shù)調(diào)用式,例如:傳遞進(jìn)去的函數(shù)名是doSomething,要傳回的數(shù)據(jù)是:這里是某車在使用簡單的JSONP,那么后臺(tái)返回的即為doSomething('這里是某車在使用簡單的JSONP')
  • 客戶端再調(diào)用執(zhí)行之前聲明的回調(diào)函數(shù)(doSomething),對返回的數(shù)據(jù)進(jìn)行操作

??封裝

但是在真正的開發(fā)中,我們不可能寫一堆<script>標(biāo)簽在那里,所以我們需要對jsonp進(jìn)行封裝

    function jsonp({url, params, callback}){
      return new Promise((resolve, reject) => {
      //動(dòng)態(tài)創(chuàng)建script標(biāo)簽
        let script = document.createElement('script');
        //處理傳入的參數(shù)
        params = {...params, callback};
         //轉(zhuǎn)換參數(shù)表達(dá)式
        let arr = []
        for(let key in params) {
          arr.push(`${key}=${params[key]}`)
        }
        //在路徑中,參數(shù)用 & 隔開
        script.src = `${url}?${arr.join('&')}`
        //添加 script 標(biāo)簽
        document.body.appendChild(script);
        //聲明回調(diào)函數(shù)
        window[callback] = function(data) {
        //執(zhí)行異步函數(shù)
          resolve(data);
          //請求完后移除該script標(biāo)簽
          document.body.removeChild(script)
        }
      })
    }
  • 使用
   jsonp({
      url:'http://localhost:3000/test',
      params:{ args:'這個(gè)是參數(shù)' },
      callback: 'doSomething'
    }).then(res=>{
      console.log(res) 
    })

??優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn): 簡單兼容性好,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問的問題
  • 缺點(diǎn): 僅支持get方法具有局限性,不安全可能會(huì)遭受XSS攻擊

CORS(Cross-Origin Resource Sharing)

  • 實(shí)現(xiàn)CORS的關(guān)鍵在于后端:服務(wù)端設(shè)置Access-Control-Allow-Origin就可以開啟 CORS。 該屬性表示哪些域名可以訪問資源,如果設(shè)置通配符則表示所有網(wǎng)站都可以訪問資源
  • 我們可以將請求分類為簡單請求和非簡單請求

簡單請求

判定:

請求方法是以下方三種方法之一

  • HEAD
  • GET
  • POST

請求頭僅包含安全的字段,如以下幾種字段

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三個(gè)值 application/x-www-form-urlencoded、multipart/form-data、text/plain

請求過程

  • 客戶端代碼
    btn.addEventListener('click',()=>{
      const xhr = new XMLHttpRequest();
      xhr.open('get', 'http://localhost:3000/test'); //向端口號(hào)為3000的發(fā)起請求
      xhr.send();
      xhr.onreadystatechange = function(){
        if(xhr.readyState == 4) {
          if(xhr.status >= 200 && xhr.status < 300) {
            console.log(xhr.response) //如果請求成功,則打印后臺(tái)返回的數(shù)據(jù)
          }
        }
      }
    })
  • 服務(wù)端設(shè)置
app.get('/test',(req,res)=>{
    //通過res.send()方法-將處理好的內(nèi)容,發(fā)送給客戶
    res.send(`你好呀某車,你已經(jīng)成功發(fā)起請求了`)
})
  • 當(dāng)你發(fā)送請求的時(shí)候(客戶端為5500端口,服務(wù)端為3000端口),什么也不設(shè)置就會(huì)報(bào)跨域錯(cuò)誤

  • 此時(shí)我們看一下當(dāng)瀏覽器會(huì)給它的請求頭加上Origin,值為它本身的協(xié)議+域名+端口,這個(gè)時(shí)候服務(wù)器就能知道是誰在對他發(fā)送請求

  • 那么服務(wù)器如果想要允許它訪問的話,則在響應(yīng)頭加上Access-Control-Allow-Origin字段,值可以為*表示允許所有源的訪問,也可以為具體的源,我們這里給他設(shè)置為我們上述的Origin值,同時(shí)也加上Access-Control-Allow-Methods字段,設(shè)置可訪問的請求方法
app.all("*",function(req,res,next){
    //設(shè)置允許跨域的域名,*代表允許任意域名跨域
    res.header("Access-Control-Allow-Origin","http://127.0.0.1:5500");
    res.header("Access-Control-Allow-Methods",'PUT,POST,GET,DELETE,OPTIONS')
    next();
})
  • 此時(shí)你再點(diǎn)擊發(fā)送請求就會(huì)發(fā)現(xiàn):請求已經(jīng)能夠正常返回了

  • 響應(yīng)頭顯示的Access-Control-Allow-Origin即為我們可訪問的源

復(fù)雜請求

  • 我們上述已經(jīng)講過什么是簡單請求了,那么不符合上述條件的即為復(fù)雜請求
  • 復(fù)雜請求發(fā)起請求的時(shí)候則是會(huì)在正式通信之前進(jìn)行一次預(yù)檢請求(preflight request)
  • 瀏覽器先詢問服務(wù)器,當(dāng)前源當(dāng)前請求是否可以訪問服務(wù)器資源,只有得到正確的答復(fù),才會(huì)進(jìn)行正式的請求

請求過程

我們依舊使用上面的代碼,然后就請求方式改為put,此時(shí)發(fā)送的即為復(fù)雜請求,可以看到發(fā)送了兩次請求,由于我們put方法在上述已經(jīng)被設(shè)置為可訪問的方法,所以現(xiàn)在預(yù)檢可以通過,我們也能正常請求到資源

如果我們將put方法從Access-Cntrol-Allow-Methods移除,此時(shí)再進(jìn)行請求,則發(fā)提示,在預(yù)檢請求中發(fā)送PUT方法是不被允許的

此時(shí)test正式請求則報(bào)CORS錯(cuò)誤

寫到這里,我就想到了曾經(jīng)看過的面試題:跨域請求如何攜帶cookie

擴(kuò)展

  • 但是我想測試的時(shí)候受到了SameSite的限制,不允許第三方cookie,本來想要關(guān)掉瀏覽器設(shè)置的,搜索了一下發(fā)現(xiàn)這個(gè)方法自從版本91之后就用不了,那么淺淺說一下方法就得了
  • 只需要前端在發(fā)送Ajax請求的時(shí)候?qū)ithCredentials設(shè)置為true
    const xhr = new XMLHttpRequest();
    xhr.withCredentials = true;
  • 后端設(shè)置"Access-Control-Allow-Credentials為true,同時(shí)注意Access-Control-Allow-Origin值不為*
    res.header("Access-Control-Allow-Credentials", "true");

缺點(diǎn)

IE10以下不支持

小結(jié):后端是關(guān)鍵,主要是設(shè)置Access-Control-Allow-Origin

關(guān)于postMessage和webSocket的跨域方案我寫在嗦嗦postMessage和webSocket這里了

以上就是簡單易懂的JSONP和CORS跨域方案詳解的詳細(xì)內(nèi)容,更多關(guān)于JSONP CORS跨域方案的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 動(dòng)態(tài)讀取JSON解析鍵值對的方法

    動(dòng)態(tài)讀取JSON解析鍵值對的方法

    這篇文章主要介紹了動(dòng)態(tài)讀取JSON解析鍵值對的方法,需要的朋友可以參考下
    2014-06-06
  • Javascript模板技術(shù)

    Javascript模板技術(shù)

    Javascript模板技術(shù)...
    2007-04-04
  • js 判斷當(dāng)前時(shí)間是否處于某個(gè)一個(gè)時(shí)間段內(nèi)

    js 判斷當(dāng)前時(shí)間是否處于某個(gè)一個(gè)時(shí)間段內(nèi)

    這篇文章主要介紹了js 判斷當(dāng)前時(shí)間是否處于某個(gè)一個(gè)時(shí)間段內(nèi),使用 jutils - JavaScript常用函數(shù)庫的 isDuringDate 函數(shù)來實(shí)現(xiàn),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2019-09-09
  • JavaScript使用showdown實(shí)現(xiàn)markdown預(yù)覽功能

    JavaScript使用showdown實(shí)現(xiàn)markdown預(yù)覽功能

    Showdown.js 是一個(gè)JavaScript庫,用于將Markdown文本轉(zhuǎn)換為HTML,這篇文章將給大家介紹了JavaScript使用showdown實(shí)現(xiàn)markdown預(yù)覽功能,文中通過代碼示例給大家講解的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • 利用Query+bootstrap和js兩種方式實(shí)現(xiàn)日期選擇器

    利用Query+bootstrap和js兩種方式實(shí)現(xiàn)日期選擇器

    日期選擇器在我們平時(shí)開發(fā)的時(shí)候經(jīng)常要用到,下面這篇文章主要給大家介紹了利用Query+bootstrap和js這兩種方式實(shí)現(xiàn)日期選擇器的方法,文中兩種方法都給出了詳細(xì)的示例代碼,有需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-01-01
  • 分享JavaScript的?3?種工廠模式的用法

    分享JavaScript的?3?種工廠模式的用法

    這篇文章主要分享JavaScript的?3?種工廠模式,工廠模式是設(shè)計(jì)模式中最常用的設(shè)計(jì)模式之一,這種類型的設(shè)計(jì)模式屬于創(chuàng)建型模式,它提供了一種創(chuàng)建對象的最佳方式,下文關(guān)于工廠模式的更多相關(guān)資料需要的小伙伴可以參考一下
    2022-04-04
  • 8種js前端常見跨域解決方案

    8種js前端常見跨域解決方案

    這篇文章主要為大家詳細(xì)介紹了在前端開發(fā)中,常見的跨域解決方案,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,有需要的小伙伴可以了解下
    2023-09-09
  • 前端處理文本換行展示4種處理方法

    前端處理文本換行展示4種處理方法

    在處理前端顯示后端傳遞的包含換行符的文本時(shí),可以通過多種方法實(shí)現(xiàn)換行顯示,這篇文章主要介紹了前端處理文本換行展示4種處理方法,這些方法幫助前端正確展示格式化文本,解決了文本堆疊的問題,需要的朋友可以參考下
    2024-10-10
  • Javascript通過overflow控制列表閉合與展開的方法

    Javascript通過overflow控制列表閉合與展開的方法

    這篇文章主要介紹了Javascript通過overflow控制列表閉合與展開的方法,設(shè)計(jì)javascript動(dòng)態(tài)操作頁面元素與樣式的相關(guān)技巧,需要的朋友可以參考下
    2015-05-05
  • JScript中的undefined和"undefined"的區(qū)別

    JScript中的undefined和"undefined"的區(qū)別

    JScript中的undefined和"undefined"的區(qū)別...
    2007-03-03

最新評(píng)論