溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Node.js中怎么對CORS進(jìn)行處理

發(fā)布時間:2021-07-20 16:33:22 來源:億速云 閱讀:255 作者:Leah 欄目:web開發(fā)

今天就跟大家聊聊有關(guān)Node.js中怎么對CORS進(jìn)行處理,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

什么是CORS

CORS 是“跨域資源共享”的簡寫。它是一種允許或限制向 Web 服務(wù)器上請求資源的機(jī)制,具體取決于進(jìn)行 HTTP 請求的位置。

這種策略用于保護(hù)特定 Web 服務(wù)器免受其他網(wǎng)站或域的訪問。只有允許的域才能訪問服務(wù)器中的文件,例如樣式表、圖像或腳本等。

假設(shè)你當(dāng)前使用的是 http://example.com/page1,并且你引用的是來自 http://image.com/myimage.jpg  的圖片,那么除非 http://image.com 允許與 http://example.com 進(jìn)行跨域共享,否則將無法獲取該圖像。

每個 HTTP 請求頭中都有一個名為 origin 的頭。它定義了域請求的來源??梢杂眠@個頭的信息來限制引用你服務(wù)器上的資源。

默認(rèn)來自任何其他來源的請求都會受到瀏覽器的限制。

例如當(dāng)開發(fā)時如果用的是 React 或 Vue 這類的前端庫,則前端應(yīng)用將運行在 http://localhost:3000 上,同時,你的  Express 服務(wù)器可能正在其他端口上運行,例如 http://localhost:2020。這時就需要在這些服務(wù)器之間允許 CORS。

如果你在瀏覽器控制臺中看到下圖這類的錯誤。問題可能出在 CORS 限制上:

Node.js中怎么對CORS進(jìn)行處理

chrome cors

如果我們需要提供公共 API 并希望控制對某些資源的訪問和使用方式時,CORS 能夠發(fā)揮很大的作用。

另外,如果想在其他網(wǎng)頁上使用自己的 API 或文件,也可以簡單地將 CORS 配置為允許自己引用,同時把其他人拒之門外。

用 Express 配置 CORS

首先創(chuàng)建一個新的項目,并創(chuàng)建目錄結(jié)構(gòu),然后使用默認(rèn)設(shè)置運行 npm init:

$ mkdir myapp $ cd myapp $ npm init -y

接下來安裝所需的模塊。我們將使用 express 和 cors 中間件:

$ npm i --save express $ npm i --save cors

然后,開始創(chuàng)建一個簡單的有兩個路由的 Web 程序,用來演示 CORS 的工作原理。

首先創(chuàng)建一個名為 index.js 的文件,用來充當(dāng) Web 服務(wù)器,并實現(xiàn)幾個請求處理函數(shù):

const express = require('express'); const cors = require('cors');  const app = express();  app.get('/', (req, res) => {     res.json({         message: 'Hello World'     }); });  app.get('/:name', (req, res) => {     let name = req.params.name;      res.json({         message: `Hello ${name}`     }); });  app.listen(2020, () => {     console.log('server is listening on port 2020'); });

運行服務(wù)器:

$ node index.js

訪問 http://localhost:2020/ 服務(wù)器應(yīng)該返回 JSON 消息:

{   "message": "Hello World" }

訪問 http://localhost:2020/something 應(yīng)該能夠看到:

{   "message": "Hello something" }

啟用所有CORS請求

如果想為所有的請求啟用 CORS,可以在配置路由之前簡單地使用 cors 中間件:

const express = require('express'); const cors = require('cors');  const app = express();  app.use(cors())  ......

如果需要,這會允許在網(wǎng)絡(luò)上的任何位置訪問所有路由。所以在本例中,每個域都可以訪問兩條路由。

例如,如果我們的服務(wù)器在 http://www.example.com 上運行并提供諸如圖片之類的內(nèi)容,則我們允許  http://www.differentdomain.com 之類的其他域從 http://www.example.com 進(jìn)行引。

因此 http://www.differentdomain.com 上的網(wǎng)頁可以將我們的域用作圖像的來源:

<img src="http://www.example.com/img/cat.jpg">

為單個路由啟用 CORS

如果只需要其中某一個路由,可以在某個路由中將 cors 配置為中間件:

app.get('/', cors(), (req, res) => {     res.json({         message: 'Hello World'     }); });

這會允許任何域訪問特定的路由。在當(dāng)前的情況下,其他域都只能訪問 / 路由。僅在與  API(在本例中為http://localhost:2020)的相同域中發(fā)起的請求才能訪問 /:name 路由。

如果嘗試另一個來源發(fā)送請求到 / 路徑將會成功,并且會收到 Hello World 作為響應(yīng):

fetch('http://localhost:2020/')     .then(response => response.json())     .then(data => console.log(data))     .catch(err => console.error(err));

運行上面的代碼,會看到來自服務(wù)器的響應(yīng)已成功輸出到控制臺:

{     message: 'Hello World' }

如果訪問除根路徑以外的其他路徑,例如 http://localhost:2020/name 或  http://localhost:2020/img/cat.png,則此請求將會被瀏覽器阻止:

fetch('http://localhost:2020/name/janith')   .then(response => response.json())   .then(data => console.log(data))   .catch(err => console.error(err));

如果在其他 Web 應(yīng)用中運行代碼,應(yīng)該看到以下錯誤:

Node.js中怎么對CORS進(jìn)行處理

控制臺錯誤

1. 用選項配置CORS

還可以用自定義選項來配置 CORS??梢愿鶕?jù)需要配置允許的 HTTP 方法,例如 GET 和 POST。

下面是通過 CORS 選項允許單個域訪問的方法:

var corsOptions = {     origin: 'http://localhost:8080',     optionsSuccessStatus: 200 // For legacy browser support }  app.use(cors(corsOptions));

如果你在源中配置域名-服務(wù)器將允許來自已配置域的CORS。因此,在我們的例子中,可以從 http://localhost:8080  訪問該API,并禁止其他域使用。

如果發(fā)送一個 GET 請求,則任何路徑都應(yīng)該可以訪問,因為這些選項是在應(yīng)用在程序級別上的。

運行下面的代碼將請求從 http://localhost:8080 發(fā)送到 http://localhost:2020:

// fetch('http://localhost:2020/')   .then(response => response.json())   .then(data => console.log(data))   .catch(err => console.error(err));  // fetch('http://localhost:2020/name/janith')   .then(response => response.json())   .then(data => console.log(data))   .catch(err => console.error(err));

可以看到被允許從該程序和域中獲取信息。

還可以根據(jù)需要配置允許的 HTTP 方法:

var corsOptions = {     origin: 'http://localhost:8080',     optionsSuccessStatus: 200 // 對于舊版瀏覽器的支持     methods: "GET, PUT" }  app.use(cors(corsOptions));

如果從 http://localhost:8080 發(fā)送POST請求,則瀏覽器將會阻止它,因為僅支持 GET 和 PUT:

fetch('http://localhost:2020', {   method: 'POST',   body: JSON.stringify({name: "janith"}), }) .then(response => response.json()) .then(data => console.log(data)) .catch(err => console.error(err));

用函數(shù)配置動態(tài) CORS 源

如果配置不滿足你的要求,也可以創(chuàng)建函數(shù)來定制 CORS。

例如假設(shè)要允許 http://something.com 和 http://example.com 對 .jpg 文件進(jìn)行CORS共享:

const allowlist = ['http://something.com', 'http://example.com'];      const corsOptionsDelegate = (req, callback) => {     let corsOptions;      let isDomainAllowed = whitelist.indexOf(req.header('Origin')) !== -1;     let isExtensionAllowed = req.path.endsWith('.jpg');      if (isDomainAllowed && isExtensionAllowed) {         // 為此請求啟用 CORS         corsOptions = { origin: true }     } else {         // 為此請求禁用 CORS         corsOptions = { origin: false }     }     callback(null, corsOptions) }  app.use(cors(corsOptionsDelegate));

回調(diào)函數(shù)接受兩個參數(shù),第一個是傳遞 null 的錯誤,第二個是傳遞 { origin: false } 的選項。第二個參數(shù)可以是用 Express 的  request 對象構(gòu)造的更多選項。

所以 http://something.com 或 http://example.com 上的 Web 應(yīng)用將能夠按照自定義配置從服務(wù)器引用擴(kuò)展名為  .jpg 的圖片。

這樣可以成功引用資源文件:

<img src="http://yourdomain.com/img/cat.jpg">

但是下面的文件將會被阻止:

<img src="http://yourdomain.com/img/cat.png">

從數(shù)據(jù)源加載允許的來源列表作

還可以用保存在數(shù)據(jù)庫中的白名單列表或任何一種數(shù)據(jù)源來允許 CORS:

var corsOptions = {     origin: function (origin, callback) {         // 從數(shù)據(jù)庫加載允許的來源列表         // 例如:origins = ['http://example.com', 'http//something.com']         database.loadOrigins((error, origins) => {             callback(error, origins);         });     } }  app.use(cors(corsOptions));

看完上述內(nèi)容,你們對Node.js中怎么對CORS進(jìn)行處理有進(jìn)一步的了解嗎?如果還想了解更多知識或者相關(guān)內(nèi)容,請關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI