小編給大家分享一下使用Node.js如何處理CORS,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!
創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供永清網(wǎng)站建設(shè)、永清做網(wǎng)站、永清網(wǎng)站設(shè)計(jì)、永清網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、永清企業(yè)網(wǎng)站模板建站服務(wù),10余年永清做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
在本文中,我們將研究怎樣用 Express 配置 CORS 以及根據(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)行跨域共享,否則將無法獲取該圖像。
每個(gè) HTTP 請求頭中都有一個(gè)名為 origin
的頭。它定義了域請求的來源??梢杂眠@個(gè)頭的信息來限制引用你服務(wù)器上的資源。
默認(rèn)來自任何其他來源的請求都會(huì)受到瀏覽器的限制。
例如當(dāng)開發(fā)時(shí)如果用的是 React 或 Vue 這類的前端庫,則前端應(yīng)用將運(yùn)行在 http://localhost:3000
上,同時(shí),你的 Express 服務(wù)器可能正在其他端口上運(yùn)行,例如 http://localhost:2020
。這時(shí)就需要在這些服務(wù)器之間允許 CORS。
如果你在瀏覽器控制臺(tái)中看到下圖這類的錯(cuò)誤。問題可能出在 CORS 限制上:
如果我們需要提供公共 API 并希望控制對某些資源的訪問和使用方式時(shí),CORS 能夠發(fā)揮很大的作用。
另外,如果想在其他網(wǎng)頁上使用自己的 API 或文件,也可以簡單地將 CORS 配置為允許自己引用,同時(shí)把其他人拒之門外。
首先創(chuàng)建一個(gè)新的項(xiàng)目,并創(chuàng)建目錄結(jié)構(gòu),然后使用默認(rèn)設(shè)置運(yùn)行 npm init
:
$ mkdir myapp $ cd myapp $ npm init -y
接下來安裝所需的模塊。我們將使用 express
和 cors
中間件:
$ npm i --save express $ npm i --save cors
然后,開始創(chuàng)建一個(gè)簡單的有兩個(gè)路由的 Web 程序,用來演示 CORS 的工作原理。
首先創(chuàng)建一個(gè)名為 index.js 的文件,用來充當(dāng) Web 服務(wù)器,并實(shí)現(xiàn)幾個(gè)請求處理函數(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'); });
運(yùn)行服務(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
中間件:
const express = require('express'); const cors = require('cors'); const app = express(); app.use(cors()) ......
如果需要,這會(huì)允許在網(wǎng)絡(luò)上的任何位置訪問所有路由。所以在本例中,每個(gè)域都可以訪問兩條路由。
例如,如果我們的服務(wù)器在 http://www.example.com
上運(yùn)行并提供諸如圖片之類的內(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">
如果只需要其中某一個(gè)路由,可以在某個(gè)路由中將 cors
配置為中間件:
app.get('/', cors(), (req, res) => { res.json({ message: 'Hello World' }); });
這會(huì)允許任何域訪問特定的路由。在當(dāng)前的情況下,其他域都只能訪問 /
路由。僅在與 API(在本例中為http://localhost:2020
)的相同域中發(fā)起的請求才能訪問 /:name
路由。
如果嘗試另一個(gè)來源發(fā)送請求到 /
路徑將會(huì)成功,并且會(huì)收到 Hello World
作為響應(yīng):
fetch('http://localhost:2020/') .then(response => response.json()) .then(data => console.log(data)) .catch(err => console.error(err));
運(yùn)行上面的代碼,會(huì)看到來自服務(wù)器的響應(yīng)已成功輸出到控制臺(tái):
{ message: 'Hello World' }
如果訪問除根路徑以外的其他路徑,例如 http://localhost:2020/name
或 http://localhost:2020/img/cat.png
,則此請求將會(huì)被瀏覽器阻止:
fetch('http://localhost:2020/name/janith') .then(response => response.json()) .then(data => console.log(data)) .catch(err => console.error(err));
如果在其他 Web 應(yīng)用中運(yùn)行代碼,應(yīng)該看到以下錯(cuò)誤:
還可以用自定義選項(xiàng)來配置 CORS。可以根據(jù)需要配置允許的 HTTP 方法,例如 GET
和 POST
。
下面是通過 CORS 選項(xiàng)允許單個(gè)域訪問的方法:
var corsOptions = { origin: 'http://localhost:8080', optionsSuccessStatus: 200 // For legacy browser support } app.use(cors(corsOptions));
如果你在源中配置域名-服務(wù)器將允許來自已配置域的CORS。因此,在我們的例子中,可以從 http://localhost:8080
訪問該API,并禁止其他域使用。
如果發(fā)送一個(gè) GET 請求,則任何路徑都應(yīng)該可以訪問,因?yàn)檫@些選項(xiàng)是在應(yīng)用在程序級別上的。
運(yùn)行下面的代碼將請求從 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請求,則瀏覽器將會(huì)阻止它,因?yàn)閮H支持 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));
如果配置不滿足你的要求,也可以創(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ù)接受兩個(gè)參數(shù),第一個(gè)是傳遞 null
的錯(cuò)誤,第二個(gè)是傳遞 { origin: false }
的選項(xiàng)。第二個(gè)參數(shù)可以是用 Express 的 request
對象構(gòu)造的更多選項(xiàng)。
所以 http://something.com
或 http://example.com
上的 Web 應(yīng)用將能夠按照自定義配置從服務(wù)器引用擴(kuò)展名為 .jpg
的圖片。
這樣可以成功引用資源文件:
<img src="http://yourdomain.com/img/cat.jpg">
但是下面的文件將會(huì)被阻止:
<img src="http://yourdomain.com/img/cat.png">
還可以用保存在數(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));
看完了這篇文章,相信你對使用Node.js如何處理CORS有了一定的了解,想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!
新聞標(biāo)題:使用Node.js如何處理CORS
網(wǎng)站鏈接:http://www.rwnh.cn/article8/gcgiop.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供App開發(fā)、關(guān)鍵詞優(yōu)化、自適應(yīng)網(wǎng)站、網(wǎng)站建設(shè)、域名注冊、網(wǎng)站排名
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)