首頁 > web前端 > js教程 > 詳解使用Node.js怎麼處理CORS

詳解使用Node.js怎麼處理CORS

青灯夜游
發布: 2020-10-28 17:42:06
轉載
3789 人瀏覽過

詳解使用Node.js怎麼處理CORS

影片教學推薦:node js教學 

介紹

在本文中,我們將研究怎樣用Express 設定CORS 以及根據需要客製化CORS 中間件。

什麼是CORS

CORS 是「跨域資源共享」的簡寫。它是一種允許或限制向 Web 伺服器上請求資源的機制,具體取決於進行 HTTP 請求的位置。

這種策略用於保護特定 Web 伺服器免受其他網站或網域的存取。只有允許的網域才能存取伺服器中的文件,例如樣式表、圖像或腳本等。

假設你目前使用的是http://example.com/page1,而你引用的是來自http://image.com/myimage.jpg 的圖片,那麼除非http://image.com 允許與http://example.com 進行跨域共享,否則將無法取得該圖像。

每個 HTTP 請求頭中都有一個名為 origin 的頭。它定義了域請求的來源。可以用這個頭的資訊來限制引用你伺服器上的資源。

預設來自任何其他來源的請求都會受到瀏覽器的限制。

例如當開發時如果用的是React 或Vue 這類的前端函式庫,則前端應用程式將運行在http://localhost:3000 上,同時,你的Express 伺服器可能正在其他連接埠上運行,例如http://localhost:2020。這時就需要在這些伺服器之間允許 CORS。

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

詳解使用Node.js怎麼處理CORS

如果我們需要提供公共API 並希望控制對某些資源的存取和使用方式時,CORS 能夠發揮很大的作用。

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

用Express 設定CORS

先建立一個新的項目,並建立目錄結構,然後使用預設設定運行npm init

$ mkdir myapp
$ cd myapp
$ npm init -y
登入後複製

接下來安裝所需的模組。我們將使用expresscors 中間件:

$ npm i --save express
$ npm i --save cors
登入後複製

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

首先建立一個名為index.js 的文件,用來充當Web 伺服器,並實作幾個請求處理函數:

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');
});
登入後複製

執行伺服器:

$ node index.js
登入後複製

存取http://localhost:2020/ 伺服器應該回傳JSON 訊息:

{
  "message": "Hello World"
}
登入後複製

訪問http://localhost:2020/something 應該可以看到:

{
  "message": "Hello something"
}
登入後複製

啟用所有CORS請求

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

const express = require('express');
const cors = require('cors');

const app = express();

app.use(cors())

......
登入後複製

如果需要,這會允許在網路上的任何位置存取所有路由。所以在本例中,每個網域都可以存取兩條路由。

例如,如果我們的伺服器在http://www.example.com 上運行並提供諸如圖片之類的內容,則我們允許http://www .differentdomain.com 之類的其他網域從http://www.example.com 進行引。

因此http://www.differentdomain.com 上的網頁可以將我們的網域用作映像的來源:

<img  alt="詳解使用Node.js怎麼處理CORS" >
登入後複製
登入後複製
登入後複製

為單一路由啟用CORS

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

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

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

如果嘗試另一個來源發送請求到/ 路徑將會成功,並且會收到Hello World 作為回應:

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

運行上面的程式碼,會看到來自伺服器的回應已成功輸出到控制台:

{
    message: 'Hello World'
}
登入後複製

如果存取根路徑以外的其他路徑,例如 #http://localhost:2020/namehttp://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 應用程式中執行程式碼,應該會看到以下錯誤:

詳解使用Node.js怎麼處理CORS

用選項設定CORS

也可以用自訂選項來設定CORS。可以根據需要配置允許的 HTTP 方法,例如 GETPOST

下面是透過 CORS 選項允許單一網域存取的方法:

var corsOptions = {
    origin: 'http://localhost:8080',
    optionsSuccessStatus: 200 // For legacy browser support
}

app.use(cors(corsOptions));
登入後複製

如果你在源中配置域名-服务器将允许来自已配置域的CORS。因此,在我们的例子中,可以从 http://localhost:8080 访问该API,并禁止其他域使用。

如果发送一个 GET 请求,则任何路径都应该可以访问,因为这些选项是在应用在程序级别上的。

运行下面的代码将请求从 http://localhost:8080 发送到 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));
登入後複製

可以看到被允许从该程序和域中获取信息。

还可以根据需要配置允许的 HTTP 方法:

var corsOptions = {
    origin: 'http://localhost:8080',
    optionsSuccessStatus: 200 // 对于旧版浏览器的支持
    methods: "GET, PUT"
}

app.use(cors(corsOptions));
登入後複製

如果从 http://localhost:8080 发送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));
登入後複製

用函数配置动态 CORS 源

如果配置不满足你的要求,也可以创建函数来定制 CORS。

例如假设要允许 http://something.com 和 http://example.com 对 .jpg  文件进行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));
登入後複製

回调函数接受两个参数,第一个是传递 null 的错误,第二个是传递  { origin: false } 的选项。第二个参数可以是用 Express 的 request 对象构造的更多选项。

所以 http://something.comhttp://example.com 上的 Web 应用将能够按照自定义配置从服务器引用扩展名为 .jpg 的图片。

这样可以成功引用资源文件:

<img  alt="詳解使用Node.js怎麼處理CORS" >
登入後複製
登入後複製
登入後複製

但是下面的文件将会被阻止:

<img  alt="詳解使用Node.js怎麼處理CORS" >
登入後複製
登入後複製
登入後複製

从数据源加载允许的来源列表作

还可以用保存在数据库中的白名单列表或任何一种数据源来允许 CORS:

var corsOptions = {
    origin: function (origin, callback) {
        // 从数据库加载允许的来源列表
        // 例如:origins = ['http://example.com', 'http//something.com']
        database.loadOrigins((error, origins) => {
            callback(error, origins);
        });
    }
}

app.use(cors(corsOptions));
登入後複製

原文:https://stackabuse.com/handling-cors-with-node-js/

作者:Janith Kasun

更多编程相关知识,可访问:编程教学!!

以上是詳解使用Node.js怎麼處理CORS的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:segmentfault.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板