CORS和JSONP的區(qū)別,如何解決跨域問(wèn)題?

2021-10-12    前端達(dá)人

在我們了解JSONP 和 CORS 之前我們先明確一下:

我們?yōu)槭裁匆褂胏ors和jsonp呢?

實(shí)際上,cors和jsonp都是用于解決跨域問(wèn)題,當(dāng)兩個(gè)頁(yè)面的協(xié)議、域名、端口號(hào)中有一個(gè)不一致時(shí)就存在了跨域,一旦出現(xiàn)跨域,瀏覽器發(fā)送跨域請(qǐng)求后,請(qǐng)求回來(lái)的數(shù)據(jù)都會(huì)被瀏覽器所攔截,準(zhǔn)備一張圖給大家看看:

 

核心點(diǎn):如何實(shí)現(xiàn)跨域數(shù)據(jù)請(qǐng)求?(?????)

現(xiàn)下實(shí)現(xiàn)跨域數(shù)據(jù)請(qǐng)求,最主要的兩種解決方案分別是 JSONP 和 CORS 。

JSONP  出現(xiàn)的早,兼容性好(兼容低版本 IE )。是前端程序員為了解決跨域問(wèn)題,被迫想出來(lái)的一種 臨時(shí)解決方案,最主要的缺點(diǎn) 是只支持 GET 請(qǐng)求,不支持 POST 請(qǐng)求。
CORS  出現(xiàn)的較晚,它是 W3C 標(biāo)準(zhǔn),屬于跨域 Ajax 請(qǐng)求的根本解決方案。支持 GET 和 POST 請(qǐng) 求。缺點(diǎn) 是不兼容某些低版本的瀏覽器。

什么是JSONP(???)

JSONP (JSON with Padding) 是 JSON 的一種“使用模式”,可用于解決主流瀏覽器的跨域數(shù)據(jù)訪問(wèn)的問(wèn)題。

JSONP的實(shí)現(xiàn)原理(???) 

  1. 概念:瀏覽器端通過(guò) <script> 標(biāo)簽的 src 屬性,請(qǐng)求服務(wù)器上的數(shù)據(jù),同時(shí),服務(wù)器返回一個(gè)函數(shù)的調(diào)用。這種請(qǐng)求數(shù)據(jù)的方式叫做 JSONP

  2. 特點(diǎn): 

   JSONP 不屬于真正的 Ajax 請(qǐng)求,因?yàn)樗鼪](méi)有使用 XMLHttpRequest 這個(gè)對(duì)象

    JSONP 僅支持 GET 請(qǐng)求,不支持 POST、PUT、DELETE 等請(qǐng)求

什么是CORS(?????)

  1. CORS (跨域資源共享) 由一系列 HTTP 響應(yīng)頭組成,這些 HTTP 響應(yīng)頭決定瀏覽器 是否阻止前端 JS 代碼跨域獲取資源

  2. 瀏覽器的同源安全策略默認(rèn)會(huì)阻止網(wǎng)頁(yè)“跨域”獲取資源。但如果接口服務(wù)器配置了 CORS 相關(guān)的 HTTP 響應(yīng)頭,就可以解除瀏覽器端的跨域訪問(wèn)限制

 

 

下面分別向大家演示通過(guò)CORS和JSONP實(shí)現(xiàn)跨域的案例:

一、通過(guò)CORS中間件解決跨域問(wèn)題 :

index.html文件代碼演示:


    
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <script src="jquery.min.js"></script>
  9. </head>
  10. <body>
  11. <button class="get">get請(qǐng)求</button>
  12. <button class="post">post請(qǐng)求</button>
  13. <script>
  14. $('.get').on('click', function() {
  15. $.ajax({
  16. method: 'get',
  17. url: 'http://127.0.0.1/api/get?name=hua&age=18',
  18. success: function(res) {
  19. console.log(res);
  20. }
  21. })
  22. })
  23. $('.post').on('click', function() {
  24. $.ajax({
  25. method: 'post',
  26. url: 'http://127.0.0.1/api/post',
  27. data: {
  28. name: 'lajitong',
  29. age: '111'
  30. },
  31. success: function(res) {
  32. console.log(res);
  33. }
  34. })
  35. })
  36. </script>
  37. </body>
  38. </html>

此時(shí)會(huì)出現(xiàn)跨域問(wèn)題,我們需要使用 cors 中間件解決跨域問(wèn)題

  1. cors 是 Express 的一個(gè)第三方中間件。通過(guò)安裝和配置 cors 中間件,可以很方便地解決跨域問(wèn)題

  2. 使用步驟

    • 安裝中間件: npm install cors

    • 導(dǎo)入中間件: const cors = require('cors')

    • 配置中間件: 在路由之前調(diào)用app.use(cors())

  3. express接口案例代碼


    
  1. // 導(dǎo)入 express 模塊
  2. const express = require('express')
  3. // 創(chuàng)建 express 的服務(wù)器實(shí)例
  4. const app = express()
  5. // 導(dǎo)入中間件
  6. const cors = require('cors')
  7. // 配置中間件
  8. app.use(cors())
  9. // 配置解析表單數(shù)據(jù)的中間件
  10. app.use(express.urlencoded({ extended: false }))
  11. // 導(dǎo)入路由模塊(被單獨(dú)分離后導(dǎo)入)
  12. const router = require('./apiRouter')
  13. // 把路由模塊,注冊(cè)到 app 上
  14. app.use('/api', router)
  15. // 調(diào)用 app.listen 方法,指定端口號(hào)并啟動(dòng) web 服務(wù)器
  16. app.listen(80, () => {
  17. console.log('http://127.0.0.1')
  18. })

apiRouter路由文件代碼:


    
  1. const express = require('express');
  2. const router = express.Router();
  3. router.get('/get', (req, res) => {
  4. const query = req.query;
  5. res.send({
  6. status: 0,
  7. msg: 'get請(qǐng)求成功',
  8. data: query
  9. })
  10. })
  11. router.post('/post', (req, res) => {
  12. // const body = req.body; //獲取客戶端請(qǐng)求的數(shù)據(jù)
  13. res.send({
  14. status: 0,
  15. msg: 'post請(qǐng)求成功',
  16. data: req.body
  17. })
  18. })
  19. module.exports = router;

在終端中運(yùn)行express接口代碼后打開index.html文件并點(diǎn)擊get及post按鈕得到請(qǐng)求結(jié)果:

 二、通過(guò)JSONP中間件解決跨域問(wèn)題 :

創(chuàng)建 JSONP 接口的注意事項(xiàng)

  1. 如果項(xiàng)目中已經(jīng)配置了 CORS 跨域資源共享,為了防止沖突,必須在配置 CORS 中間件之前聲明 JSONP 的接口

    否則 JSONP 接口會(huì)被處理成開啟了 CORS 的接口

  2. 實(shí)現(xiàn)步驟:

        (1)獲取客戶端發(fā)送過(guò)來(lái)的回調(diào)函數(shù)的名字

        (2)得到要通過(guò) JSONP 形式發(fā)送給客戶端的數(shù)據(jù)

        (3)根據(jù)前兩步得到的數(shù)據(jù),拼接出一個(gè)函數(shù)調(diào)用的字符串

        (4)把上一步拼接得到的字符串,響應(yīng)給客戶端的 <script> 標(biāo)簽進(jìn)行解析執(zhí)行

案例代碼如下:


    
  1. //導(dǎo)入express模塊
  2. const express = require('express');
  3. //創(chuàng)建express服務(wù)器實(shí)例
  4. const app = express();
  5. //掛載路由
  6. app.get('/jsonp', (req, res) => {
  7. // 通過(guò)解構(gòu)req.query客戶端通過(guò)查詢字符串的形式發(fā)送到客戶端的參數(shù)fn
  8. const { callback } = req.query
  9. //在服務(wù)器端定義一個(gè)obj對(duì)象
  10. const obj = {
  11. uname: 'zjj',
  12. age: '18'
  13. }
  14. //obj對(duì)象轉(zhuǎn)為res.send可處理的字符串形式后從服務(wù)器端相應(yīng)回調(diào)函數(shù)至客戶端
  15. res.send(`${callback}(${JSON.stringify(obj)})`)
  16. })
  17. app.listen(80, () => {
  18. console.log('http://127.0.0.1');
  19. })

創(chuàng)建jsonp.html客戶端來(lái)接收服務(wù)器端響應(yīng)過(guò)來(lái)的回調(diào)函數(shù),代碼如下:

url中callback=fn為客戶端發(fā)送請(qǐng)求攜帶的參數(shù) 既服務(wù)器端中的req.query.callback


    
  1. <script>
  2. function fn(res) {
  3. console.log(res);
  4. }
  5. </script>
  6. <script src="http://127.0.0.1/jsonp?callback=fn"></script>




藍(lán)藍(lán)設(shè)計(jì)建立了UI設(shè)計(jì)分享群,每天會(huì)分享國(guó)內(nèi)外的一些優(yōu)秀設(shè)計(jì),如果有興趣的話,可以進(jìn)入一起成長(zhǎng)學(xué)習(xí),請(qǐng)掃碼藍(lán)小助,報(bào)下信息,藍(lán)小助會(huì)請(qǐng)您入群。歡迎您加入噢~~希望得到建議咨詢、商務(wù)合作,也請(qǐng)與我們聯(lián)系。

分享此文一切功德,皆悉回向給文章原作者及眾讀者.

轉(zhuǎn)自:csdn
免責(zé)聲明:藍(lán)藍(lán)設(shè)計(jì)尊重原作者,文章的版權(quán)歸原作者。如涉及版權(quán)問(wèn)題,請(qǐng)及時(shí)與我們?nèi)〉寐?lián)系,我們立即更正或刪除。

藍(lán)藍(lán)設(shè)計(jì)www.bouu.cn )是一家專注而深入的界面設(shè)計(jì)公司,為期望卓越的國(guó)內(nèi)外企業(yè)提供卓越的UI界面設(shè)計(jì)、BS界面設(shè)計(jì) 、 cs界面設(shè)計(jì) 、 ipad界面設(shè)計(jì) 、 包裝設(shè)計(jì) 、 圖標(biāo)定制 、 用戶體驗(yàn) 、交互設(shè)計(jì)、 網(wǎng)站建設(shè) 、平面設(shè)計(jì)服務(wù)

分享本文至:

日歷

鏈接

個(gè)人資料

存檔