客戶端-服務(wù)器關(guān)系。

這樣應(yīng)用程序的前端和后端就可以相互通信和共享資源。但是 Web 應(yīng)用程序的客戶端始終在瀏覽器上運(yùn)行。這就產(chǎn)生了一些復(fù)雜情況,因?yàn)榍岸碎_發(fā)人員無法完全控制很多事情。 

瀏覽器強(qiáng)制實(shí)施同源策略

網(wǎng)絡(luò)瀏覽器已經(jīng)存在了幾十年。它們的存在改變了網(wǎng)絡(luò)應(yīng)用程序的工作方式,尤其是其安全性方面。這就是為什么瀏覽器默認(rèn)對所有客戶端應(yīng)用程序?qū)嵤┩床呗浴4瞬呗砸?guī)定,如果在瀏覽器上運(yùn)行的應(yīng)用程序從與您的應(yīng)用程序來源不同的服務(wù)器請求資源,則瀏覽器將默認(rèn)阻止該請求。

但這個起源到底是什么?

來源通常由域名、端口號和方案組成。方案表示 URL 的協(xié)議 — 例如,它是 HTTP 還是 HTTPS。域名和端口號一起表示 URL 中您或其他用戶可見的部分。 

因此,如果您的 Web 應(yīng)用程序在 abcd.com 上運(yùn)行,并且您嘗試請求位于 xyz.com 的資源,則瀏覽器(您的 abcd.com 正在其中運(yùn)行并向 xyz.com 發(fā)出請求)將啟動其同源策略。 

你需要 CORS!

現(xiàn)在的問題是,你的應(yīng)用程序需要來自不同來源的提供商的資源。這個問題有很多用例。 

首先,您可以為您的 Web 應(yīng)用程序采用解耦的客戶端-服務(wù)器架構(gòu)。這意味著您可以擁有一個在 abcd.com 上運(yùn)行的完全獨(dú)立的前端和一個在 xyz.com 上運(yùn)行的獨(dú)立后端。您需要它們相互交互,但由于它們位于不同的域上,并且本質(zhì)上來自不同的來源,因此您無法實(shí)現(xiàn)。 

另一個用例是與第三方 API 和服務(wù)交互。您可以使用第三方 API 在您的網(wǎng)站上進(jìn)行付款,或者使用第三方服務(wù)來處理應(yīng)用程序上的身份驗(yàn)證。

無論用例如何,第三方服務(wù)總是會與您的應(yīng)用程序有不同的來源。 

為了讓您的應(yīng)用程序與不同來源的 Web 服務(wù)器和 API 進(jìn)行交互,您需要 CORS。CORS 將告訴瀏覽器取消其同源策略并啟用相應(yīng)客戶端和服務(wù)器之間的資源共享。這就是 CORS 對您有所幫助的原因和方式。如果您想了解有關(guān) CORS 的更多信息,請查看這本深入探討該主題的 精彩指南。

現(xiàn)在我們來回答第一個問題,誰來實(shí)際設(shè)置 CORS?

服務(wù)器已啟用 CORS

由于資源是從服務(wù)器檢索的,因此服務(wù)器可以完全控制哪些客戶端可以訪問它。出于同樣的原因,啟用 CORS 也是在服務(wù)器端完成的。 

這意味著您的應(yīng)用程序中將有一個后端組件。該后端組件應(yīng)該確保將為哪些 URL 或客戶端啟用 CORS。 

現(xiàn)在來回答第二個問題。至于如何啟用 CORS,讓我們寫一些代碼吧!

使用 TypeScript 創(chuàng)建 Node.js 項(xiàng)目

在本教程中,我們將重點(diǎn)介紹使用 Node.js 和 Express 構(gòu)建的后端,該后端使用 TypeScript 編寫。我有一個類似的 JavaScript 教程,您也可以查看。?

在您選擇的目錄中,通過運(yùn)行以下命令創(chuàng)建一個新的 npm 項(xiàng)目: 

mkdir nodejs-ts-cors && npm init -y

然后,我們通過運(yùn)行以下命令安裝 TypeScript 作為開發(fā)依賴項(xiàng): 

npm i --save-dev typescript

如果您打開項(xiàng)目,您現(xiàn)在應(yīng)該有一個package.json文件、一個package-lock.json文件和一個node_modules文件夾。 

接下來,在項(xiàng)目根目錄下創(chuàng)建一個名為tsconfig.json的文件。此文件將指定 TypeScript 構(gòu)建項(xiàng)目的所有配置。在其中添加以下代碼:

{
"compilerOptions": {
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist"
},
"lib": ["es2015"]
}

最后,我們需要替換package.json文件中的主要條目:

...
"main": "dist/server.js"
...

并添加一個新腳本,該腳本可以在從 TypeScript 編譯后在運(yùn)行時直接運(yùn)行我們的 JavaScript 代碼:

...  
"scripts": {
"start": "tsc && node dist/server.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
...

創(chuàng)建一個 Express 和 TypeScript 服務(wù)器

在創(chuàng)建用于發(fā)送資源的端點(diǎn)之前,我們需要設(shè)置服務(wù)器。要創(chuàng)建服務(wù)器,我們將安裝 Express,如下所示: 

npm i --save express@4.17.1

要將 Express 與 TypeScript 的類和類型一起使用,我們還需要安裝types/express, 如下所示: 

npm install -save-dev @types/express@4.17.1

現(xiàn)在在根目錄中創(chuàng)建一個名為server.ts的文件,內(nèi)容如下:

const app:any = express();
const port:Number = 3000;

app.get('/', (req, res) => {
res.send('NodeJS + Express + Typescript App Up! ??');
});

app.listen(port, () => {
console.log(Server running on port ${port}); });

如果你現(xiàn)在運(yùn)行命令npm run start,我們的 TypeScript 編譯器將編譯我們的server.ts文件,在dist/server.js文件中生成其等效的 JavaScript 代碼,并在本地主機(jī)上提供服務(wù)。如果你訪問“http://localhost:3000”,你應(yīng)該會得到以下響應(yīng):

TypeScript CORS 指南:它是什么以及如何啟用它 - 圖片 3

您將收到的回復(fù)視圖。

太棒了!現(xiàn)在讓我們創(chuàng)建一個發(fā)回一些資源的簡單端點(diǎn)。

創(chuàng)建 REST API

讓我們編寫一個簡單的 REST API 來返回一些 JSON 數(shù)據(jù)。我們將創(chuàng)建一個端點(diǎn)/dog來返回一些關(guān)于(您猜對了)狗的 JSON 數(shù)據(jù)!

app.get('/dog',(req,res)=>{
res.json({
'name':'Bruno',
'age':'5',
'image':'https://post.medicalnewstoday.com/wp-content/uploads/sites/3/2020/02/322868_1100-800x825.jpg'
})
})

太棒了!現(xiàn)在讓我們測試一下。您需要重新運(yùn)行npm run start 命令。如果您現(xiàn)在訪問“http://localhost:3000/dog”,您應(yīng)該會得到以下響應(yīng):

TypeScript CORS 指南:它是什么以及如何啟用它 - 圖片 4

您將收到的回復(fù)視圖。

因此,現(xiàn)在 TypeScript 中似乎有一個 GET API 可以返回一些資源。但是,當(dāng)我們從 React 或 Angular 等客戶端應(yīng)用程序請求此資源時會發(fā)生什么?

CORS 錯誤

為了演示這一點(diǎn),我們將創(chuàng)建一個 React 應(yīng)用并嘗試向上述端點(diǎn)發(fā)出請求。首先,讓我們通過運(yùn)行以下命令創(chuàng)建一個新的 React 項(xiàng)目:

npx create-react-app dog-app

完成后,打開項(xiàng)目并使用以下代碼更新App.js文件:

import {useState} from 'react';
import './App.css';

function App() {
const [dogData,setDogData]=useState();
const getDogData=async()=>{
const response=await fetch('http://localhost:3000/dog');
const data=await response.json();
setDogData(data);
}
return (
<div className="App">
<header className="App-header">
<button onClick={getDogData} disabled={dogData}>Get Dogg!</button>
{dogData &&
<div>
<h3>{dogData?.name}</h3>
<h3>{dogData?.age}</h3>
<img src={dogData?.image} />
</div>
}
</header>
</div>
);
}

export default App;

此代碼在頁面上呈現(xiàn)一個按鈕。單擊按鈕時,它會調(diào)用一個函數(shù),該函數(shù)向端點(diǎn)“http://localhost:3000/dog”發(fā)出請求。然后,它會獲取收到的資源或 JSON 數(shù)據(jù),將該數(shù)據(jù)推送到應(yīng)用組件的狀態(tài),并將其顯示在頁面上。 

讓我們測試一下。您必須運(yùn)行 npm 才能開始運(yùn)行它,并且它可能會要求您在其他端口上打開此應(yīng)用程序,因?yàn)槲覀円呀?jīng)將端口 3000 用于 TypeScript 和 Express 后端服務(wù)器。一旦它進(jìn)入您的瀏覽器,如果您按下Get Dogg!按鈕,您應(yīng)該會在控制臺上收到如下錯誤:

TypeScript CORS 指南:它是什么以及如何啟用它 - 圖片 5

點(diǎn)擊“Get Dogg!”按鈕后出現(xiàn) CORS 錯誤。

啟用 CORS

我們需要消除該 CORS 錯誤。一種解決方案是,我們可以為該客戶端手動啟用端點(diǎn)上的 CORS。我們可以通過在響應(yīng)的標(biāo)頭上添加鍵“Access-Control-Allow-Origin”來實(shí)現(xiàn)這一點(diǎn)。此鍵的值是您希望為其啟用 CORS 的應(yīng)用程序或客戶端的 URL。 

在我們的例子中,它是“http://localhost:3001”或你的 React 應(yīng)用程序正在運(yùn)行的任何位置。

app.get('/dog',(req,res)=>{
res.set('Access-Control-Allow-Origin', 'http://localhost:3001');
...
})

現(xiàn)在您的 React 應(yīng)用程序?qū)⒛軌驈摹癶ttp://localhost:3000”訪問資源。如果您刷新后端,請?jiān)俅螁螕?strong>“Get Dogg!”按鈕。

TypeScript CORS 指南:它是什么以及如何啟用它 - 圖片 6

Get Dogg! 按鈕正在運(yùn)行。

我們現(xiàn)在可以從 TypeScript API 中取回數(shù)據(jù)!太棒了。我們已成功在 Node.js 和 TypeScript 應(yīng)用程序中啟用 CORS。

結(jié)論

還有另一種在 Node.js 和 TypeScript 服務(wù)器中啟用 CORS 的巧妙方法。您可以使用 CORS 中間件依賴項(xiàng),它允許您以更自定義的方式輕松配置 CORS。Node.js 的實(shí)現(xiàn)類似于 TypeScript,您可以在本教程中了解如何執(zhí)行此操作。 

如果您想要針對這個古老的 CORS 問題進(jìn)行前端特定的破解,這里有針對ReactAngular的解決方案。但請記住,處理 CORS 的正確方法是在服務(wù)器上設(shè)置適當(dāng)?shù)脑L問控制允許來源。但總而言之,我希望這足以幫助您掌握 CORS 并了解如何在 Node.js 和 TypeScript 應(yīng)用程序中啟用它。

上一篇:

.NET命令注入:示例及預(yù)防

下一篇:

.NET Open Redirect 指南:示例與預(yù)防
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊

多API并行試用

數(shù)據(jù)驅(qū)動選型,提升決策效率

查看全部API→
??

熱門場景實(shí)測,選對API

#AI文本生成大模型API

對比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個渠道
一鍵對比試用API 限時免費(fèi)

#AI深度推理大模型API

對比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費(fèi)