成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

跨域是個什么鬼,你搞明白了嗎?

網絡 通信技術
跨域是個老生常談的話題了,最近不管在和后端聯調,或者搞微前端的時候都會遇到,正好寫篇文章來總結一下吧。

[[433686]]

跨域是個老生常談的話題了,最近不管在和后端聯調,或者搞微前端的時候都會遇到,正好寫篇文章來總結一下吧。

跨域是什么

這里的“跨域”指的是不同源之間的資源訪問。只要請求的 url 有以下不同,都屬于“跨域”:

  • 協議: http, https, ...
  • 域名
  • 端口

有人可能會覺得,我自己網站肯定只訪問自己服務器,肯定都是部署在一個域名的呀。

但是有的時候,一個網頁可能要對接后端多個服務:一會對接支付,一會對接用戶信息。每個組的后端可能都會有自己的域名。在這樣的場景下,跨域就非常常見了。

為什么會有跨域

我們常說的“跨域”問題,其實是在說“跨域”訪問的限制問題,相信大家對下面的報錯習以為常了:

這種“跨域”限制其實是 瀏覽器自帶的安全機制,只有 在瀏覽器上 發生跨域請求操作時,瀏覽器就會自動拋出上面的錯誤。

注意,這僅在瀏覽器上會出現這樣的限制,如果你用 Postman 這些工具訪問 url 是沒有“跨域”限制的,畢竟 Postman 連域名這些玩意都沒有,哪來的“跨域”。

CORS

雖然瀏覽器出于安全考慮做了“跨域”訪問的限制,但開發時不可避免會有這樣不同源資源訪問的需求,因此 W3C 就制定了 CORS(Cross-origin resource sharing 跨域資源共享) 的機制。

很多人一直以為 CORS = 跨域,其實 CORS 是一種解決“跨域”的方案。

需要注意的是,CORS 是一個“新”的協議(至少對于以前的 IE7 是新的),不僅需要瀏覽器支持,也后端服務器的支持。

瀏覽器支持沒什么好說的,就是瀏覽器版本是否支持的問題:

然后就是后端服務器支持了,服務器需要在 Response Header 上添加 Access-Control-xxx-yyy 的字段,瀏覽器識別到了,才能放行該請求。比如,最常見的就是加 Access-Control-Allow-Origin 這個返回頭,值設置為需要放行的域名。

簡單請求 VS 非簡單請求

瀏覽器將 CORS 請求分為 簡單請求 和 非簡單請求。

簡單請求 會在發送時自動在 HTTP 請求頭加上 Origin 字段,來標明當前是哪個源(協議+域名+端口),服務端來決定是否放行。

非簡單請求 則會先發一個 OPTIONS 預檢請求給服務端,當通過了再發正常的 CORS 請求。

對于 簡單請求,請求方法為以下三種之一:

  • Head
  • Post
  • Get

且 HTTP 請求頭字段不能超過以下字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type

同時 Content-Type 只能三個值:

  • application/x-www-form-urlencoded 對應普通表單
  • multipart/form-data 對應文件上傳
  • text/plain 對應文本發送(一般不怎么用)

只要不滿足上面條件的,都屬于 非簡單請求。

可能很多人會自然地覺得 POST 請求都是 非簡單請求,因為我們常看到發 POST 時,都會先發 OPTIONS。其實是因為我們一般都會傳 JSON 格式的數據,Content-Type 為 application/json,所以,這樣的 POST 請求才屬于 非簡單請求。

Access-Control-xxx-yyyy

當 CORS 請求為 簡單請求時,請求會檢測返回頭里的以下字段:

  • Access-Control-Allow-Origin:指定哪些源是可以共享資源的(包含協議、域名、端口)。
  • Access-Control-Allow-Credentials:當請求需要攜帶 Cookie 時,需要加上這個字段為 true 才能允許攜帶 Cookie。
  • Access-Control-Expose-Headers:由于 XMLHttpRequest 對象只能拿到 Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma 這 6 個基本字段。想要在拿到別的字段,就需要在這里去指定。

而當 CORS 請求為 非簡單請求時,瀏覽器會先發一個 OPTIONS 預檢(preflight)請求,這個請求會檢查如下字段:

  • Access-Control-Request-Method:指定可訪問的方法,對于非簡單請求,可能會用到 PUT,PATCH,DELETE 等 RESTful 方法,服務端需要把這些方法名也加上。
  • Access-Control-Request-Headers:指定 HTTP 請求頭會額外添加的信息。一個很常見的場景就是,后端有時候會將一些環境參數放到請求頭里,如果不用這個字段來指定放行的字段,那么就會出現“跨域”限制了。

如果 OPTIONS 請求沒有通過服務端的校驗,就會返回一個正常的 HTTP 請求,不會帶上 CORS 的返回信息,所以瀏覽器就會認定為“跨域”了。

總結一句話就是,當 Console 報哪個錯,你就在服務端返回頭上加上哪個字段就可以了。

CORS 中間件

無論對于 Express 還是 KOA,我們都不需要再手動添加上面的字段了,直接加一個 cors 中間件就可以很方便地添加上面的字段,寫起來也更優雅:

  1. var cors = require('cors'); 
  2.  
  3. var corsOptions = { 
  4.   origin: function (origin, callback) { 
  5.     // db.loadOrigins is an example call to load 
  6.     // a list of origins from a backing database 
  7.     db.loadOrigins(function (error, origins) { 
  8.       callback(error, origins) 
  9.     }) 
  10.   } 
  11.  
  12. app.use('/', cors(corsOptions), indexRouter); 

JSONP

那對于瀏覽器不支持 CORS 的情況呢?雖然目前來看是不太可能,但是在還沒有 CORS 的時代,大家是怎么解決跨域的呢?答案就是 JSONP。

它的原理也非常簡單:雖然瀏覽器限制了 HTTP 的跨域,但是沒有限制獲取 script 標簽內容的跨域請求呀。

 

當我們插入一個 <script src="xxx.com"> 標簽的時候,會發一個獲取 xxx.com 的 GET 請求,而這個 GET 請求又不存在“跨域”限制,通過這樣的方法就能解決跨域的問題了。

服務端實現:

  1. router.get('/', (req, res) =>  { 
  2.   const { callback_name } = req.query; 
  3.   res.send(`${callback_name}('hello')`) // 返回 JS 代碼,調用 callback_name 這個函數,并傳入 hello 
  4. }); 

前端實現:

  1. function jsonpCallback(params) { 
  2.   alert('執行 public/index.html 里定義的 jsonpCallback 函數,并傳入' + params + '參數'); 
  3.  
  4.  
  5. const jsonp = async () => { 
  6.   // 制作 script 標簽 
  7.   const script = document.createElement('script'); 
  8.   script.type = 'text/javascript'
  9.   script.src = 'http://localhost:9000/user?callback_name=jsonpCallback' 
  10.   // 添加標簽 
  11.   document.body.appendChild(script); 
  12.   // 拿到數據再移除 
  13.   document.body.removeChild(script); 
  14.  
  15. jsonp(); 

當調用 jsonp 函數的時候,自動創建一個 script 標簽,再把請求放到 scr 里,就會自動發起 GET 請求。服務端會直接返回一串 JavaScript 代碼,然后前端執行這段從服務端獲取來的 JS 代碼,獲取到后端數據。

跨域場景

“跨域”不僅存在于接口訪問,還會有以下場景:

  • 前端訪問跨域 URL,最常見的場景,需要后端添加 cors 的返回字段
  • 微前端:主應用和子應用之間的資源訪問可能存在“跨域”操作,需要子應用/主應用添加 cors
  • 登錄重定向:本質上和第一條一樣,不過在現象層面不太一樣。比如訪問 abc.com 時,有的網站會重定向到自己的登錄頁 passport.abc.com,如果 passport.abc.com 沒有設置 cors,也會出現跨域

總結

總的來說,我們常說的“跨域”,其實就是獲取不同源(協議+域名+端口)的資源時,瀏覽器自身 做出的限制。

在以前,開發者會用 JSONP 這種通過生成一個 script 標簽,自動發起 GET 請求的方式來解決跨域,但是這種方式非常不安全,不推薦。

到了現在,瀏覽器都已經完美支持 CORS 機制了,只需要在服務端添加對應的返回頭 Access-Control-xxx-yyy 就可以了。當瀏覽器報“跨域”錯誤時,缺哪個字段,就在服務端配哪個字段即可。

Node 端開發時,我們可以直接使用 cors 中間件來配置,就不用手寫返回頭里的字段了。

 

責任編輯:武曉燕 來源: 寫代碼的海怪
相關推薦

2022-12-30 08:35:00

2024-05-30 08:19:52

微服務架構大型應用

2022-05-04 08:38:32

Netty網絡框架

2015-05-21 15:45:13

2015-09-18 09:17:06

數據分析

2023-08-26 21:42:08

零拷貝I/O操作

2023-07-27 08:26:36

零拷貝I/O操作

2022-09-27 07:31:57

Property模式數據

2023-12-08 08:38:15

EventLoopAPI瀏覽器

2022-10-10 18:38:56

inert屬性鍵盤

2017-06-14 11:18:40

2023-12-28 08:43:28

前端算法搜索

2024-01-08 20:05:32

2022-10-19 08:19:32

動態基線預警

2022-04-07 11:15:22

PulseEventAPI函數

2018-04-03 14:49:24

2023-12-06 08:01:03

CSSPostCSS

2023-06-14 08:15:34

算法合并操作Winner

2022-10-24 20:25:40

云原生SpringJava

2024-03-27 13:33:00

MySQLInnoDB事務
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 久久久久久久久国产成人免费 | 精品国产乱码久久久久久闺蜜 | 亚洲精品一区在线观看 | 成人午夜网站 | 欧美日韩在线观看视频 | 国产羞羞视频在线观看 | 成人午夜看片 | 欧美激情精品久久久久久免费 | a级片www| 亚洲狠狠 | 中文字幕在线观 | 亚洲国产成人精品女人久久久 | 成人毛片一区二区三区 | 网页av| 精一区二区 | 蜜桃av一区二区三区 | 高清免费av | 999国产精品视频 | 精品久久久久久久久久久久久 | 久久久性色精品国产免费观看 | 涩涩视频在线观看 | 日韩在线观看精品 | 亚洲精品电影在线观看 | www.久久.com| 伊人网91| 一区二区三区久久 | 一级片视频免费观看 | 一区二区三区欧美 | 一区二区av | 亚洲天天干 | 日韩二区三区 | 欧美精品一级 | 日本一区二区三区在线观看 | 在线中文字幕视频 | 国产日韩一区二区三免费高清 | 久久久一区二区 | av网站免费| 久久久久久久久久久久久久久久久久久久 | 亚洲高清视频一区二区 | 美人の美乳で授乳プレイ | 亚洲毛片一区二区 |