App下載

怎么在Node.js中創(chuàng)建安全的REST API?創(chuàng)建安全的REST API的方法!

櫥窗的光 2021-08-30 17:53:16 瀏覽數(shù) (2739)
反饋

表中的內(nèi)容

  1. 介紹
  2. Node.js 對(duì)于 Rest API 的重要性!
  3. 什么是 REST,它如何與 Node.js 融合?在 Node.js 中創(chuàng)建和保護(hù) RESTful API!創(chuàng)建您的第一個(gè)應(yīng)用 Express API創(chuàng)建用戶(hù)模塊創(chuàng)建身份驗(yàn)證模塊
  4. 結(jié)論

一、簡(jiǎn)介

應(yīng)用程序編程接口 (API) 的炒作是普遍的。它們使軟件能夠與軟件的內(nèi)部和外部部分進(jìn)行交互,這是可擴(kuò)展性和可重用性的基本要素。

擁有公共 API 的在線幫助現(xiàn)在非常流行。這些允許其他開(kāi)發(fā)人員快速結(jié)合社交媒體登錄、信用卡債務(wù)和績(jī)效跟蹤等功能。 

他們?yōu)榇藢?shí)踐的標(biāo)準(zhǔn)是指定的 REpresentational State Transfer (REST),它與 ??Node.js 最佳開(kāi)發(fā)技術(shù)完美配合。此外,您可以閱讀一些關(guān)于 Node.js 開(kāi)發(fā)最佳實(shí)踐的最佳文章。他們可能會(huì)提供很大的幫助! 

2. Node.js 對(duì)于 Rest API 的重要性!

Node.js不是框架或庫(kù),而是由 Chrome 的 V8 JavaScript 引擎提供支持的運(yùn)行時(shí)上下文。

作為開(kāi)源項(xiàng)目,Node.js 由云計(jì)算和 Node.js 最佳開(kāi)發(fā)提供商 Joyent 贊助。該公司資助了其他幾項(xiàng)技術(shù),如 Ruby on Rails 框架,并為 Twitter 和 LinkedIn 實(shí)施了托管職責(zé)。

LinkedIn 也成為首批使用 Node.js 為其移動(dòng)應(yīng)用程序后端創(chuàng)建新項(xiàng)目的公司之一。該技術(shù)隨后被 Uber、eBay 和 Netflix 等許多技術(shù)管理員選中。

不過(guò),直到后來(lái),Node.js 服務(wù)器才開(kāi)始廣泛使用服務(wù)器端 JavaScript。這項(xiàng)技術(shù)的投資在 2017 年達(dá)到頂峰,并且仍處于領(lǐng)先地位。

Node.js IDEs 是最流行的代碼編輯器,它有 JavaScript 和 Node.js 的幫助和插件,所以它只是意味著你如何根據(jù)編碼要求自定義 IDE。但是,許多 Node.js 開(kāi)發(fā)人員稱(chēng)贊來(lái)自 VS Code、Brackets 和 WebStorm 的特定工具。

在簡(jiǎn)單的 Node.js 最佳開(kāi)發(fā)中使用中間件是一種讓開(kāi)發(fā)人員的生活更舒適的通用方法。然而,Node.js 一直是許多開(kāi)發(fā)人員創(chuàng)建新的 Restful API 的最可靠來(lái)源之一。

Node.js 的力量和趨勢(shì)使它成為一場(chǎng)激烈的辯論。但是,您可以通過(guò)學(xué)習(xí)和探索更多 Node.js Rest API 來(lái)決定。

3. 什么是 REST 以及它如何與 Node.js 融合?

REST 是 REST API 的設(shè)計(jì)模型或設(shè)計(jì)風(fēng)格。RESTful Web 應(yīng)用程序的使用因?qū)⑵渲R(shí)呈現(xiàn)為與其支持相關(guān)的數(shù)據(jù)形式而受到贊賞。

使用 Node.js 的 REST API 還有助于其客戶(hù)在設(shè)備上執(zhí)行操作,例如替換當(dāng)前資源或設(shè)計(jì)不同的資源。

為了保護(hù)您的 RESTful API,您必須開(kāi)發(fā)各種約束,而 Node.js 非常適合這一點(diǎn)。Node.js 服務(wù)器將設(shè)置 REST 的一組限制,以使 API 易于實(shí)踐和創(chuàng)建。 

它表明,剛開(kāi)始管理您的 API 的 Nodejs 開(kāi)發(fā)人員將高效快速地學(xué)習(xí)它。

此外,每當(dāng)請(qǐng)求使用 RESTful API 時(shí),Node.js 服務(wù)器都會(huì)將所請(qǐng)求資源的狀態(tài)表示分配給客戶(hù)。

3.1 在 Node.js 中創(chuàng)建和保護(hù) RESTful API!

正如您知道需要?jiǎng)?chuàng)建什么以及要求是什么一樣,這是開(kāi)始創(chuàng)建應(yīng)用程序的機(jī)會(huì)。 

首先,啟動(dòng)一個(gè)終端,將其轉(zhuǎn)移到您通常創(chuàng)建項(xiàng)目的記錄,并在那里建立一個(gè)新目錄:

mkdir express-ads-api

接下來(lái),進(jìn)入這個(gè)全新的目錄并練習(xí) npm install 來(lái)構(gòu)建一個(gè)新項(xiàng)目:

npm init -y

命令 over 將使用任何想要的屬性來(lái)構(gòu)建項(xiàng)目。如果您在文本目錄或 IDE 中啟動(dòng)此目錄,您會(huì)注意到您啟動(dòng)的 npm 命令形成了一個(gè)名為 package.json 的文件。違反此文件,您會(huì)發(fā)現(xiàn)如下內(nèi)容:

JSON:

{
  "name": "express-ads-api",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

在這一點(diǎn)上,這些數(shù)據(jù)很短,沒(méi)有那么多引人入勝的數(shù)據(jù)。然而,當(dāng)您開(kāi)始計(jì)算項(xiàng)目的任務(wù)時(shí),傾向于該文件將開(kāi)始并變得更加令人印象深刻。

隨后,您將在設(shè)計(jì)源中建立一個(gè)名為 src 的新目錄:

mkdir src

此處的目的是將所有參考代碼放在此記錄中。因此,創(chuàng)建此目錄,在其中構(gòu)建一個(gè)名為 index.js 的不同文件,并將生成的代碼附加到其中:

// ./src/index.js 

console.log('Good Morning!'); 

保留此文件后,您可以將其定向回您的計(jì)算機(jī)并發(fā)出以下命令來(lái)試驗(yàn)它:

node src

如果這按預(yù)期運(yùn)行,您會(huì)注意到“早上好!” 在您的屏幕上縮進(jìn)。

區(qū)域性工作的 Node.js 應(yīng)用程序“早安”console.log 信息.

3.2 創(chuàng)建你的第一個(gè) App Express API

現(xiàn)在,您設(shè)計(jì)的項(xiàng)目只記錄了一條潛在消息。由于這可能不是很有價(jià)值,在創(chuàng)建您的“早安!”之后。與 Node.js 一起使用,您可以開(kāi)始專(zhuān)注于創(chuàng)建RESTful API。 

為此,您首先需要在某些省份進(jìn)行投資。因此,直接到您的計(jì)算機(jī)并宣布以下命令:

npm install body-parser cors express helmet morgan

此命令將在您的設(shè)計(jì)中建立五個(gè)依賴(lài)項(xiàng):

  • body-parser:您將練習(xí)此依賴(lài)項(xiàng)以將傳入應(yīng)用程序的基礎(chǔ)轉(zhuǎn)換為 JavaScript 對(duì)象。
  • cors:使用此依賴(lài)項(xiàng)來(lái)配置 Express 以組合標(biāo)頭,聲明您的 Rest API 允許來(lái)自其他來(lái)源的請(qǐng)求。這被視為跨域資源共享 (CORS)。
  • express: Express 庫(kù)。
  • morgan:這個(gè)庫(kù)為您的 Express Rest API 提供了一些日志記錄功能。

在開(kāi)始之前的命令后,您將在您的項(xiàng)目中標(biāo)記兩個(gè)項(xiàng)目。首先,package.json 文件將包含一個(gè)稱(chēng)為依賴(lài)項(xiàng)的原始功能,以及之前的所有庫(kù)。 

這就是 NPM 確定項(xiàng)目需要哪些依賴(lài)項(xiàng)的方式。其次,您將在項(xiàng)目根目錄中看到一個(gè)名為 package-lock.json 的不同文件。 

NPM 安裝此文件以識(shí)別您在開(kāi)發(fā)時(shí)練習(xí)的特定庫(kù),因此它始終應(yīng)用相同的庫(kù)。

當(dāng) NPM 終止連接這些依賴(lài)項(xiàng)時(shí),它可能會(huì)得到一些時(shí)間,根據(jù)您的互聯(lián)網(wǎng)關(guān)系,您可以啟動(dòng) index.js 文件,并按照以下方式替換其代碼:

JavaScript:

// ./src/index.js
// importing the dependencies
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const helmet = require('helmet');
const morgan = require('morgan');
// defining the Express app
const app = express();
// defining an array to work as the database (temporary solution)
const ads = [
  {title: 'Hello, world (again)!'}
];
// adding Helmet to enhance your Rest API's security
app.use(helmet());
// using bodyParser to parse JSON bodies into JS objects
app.use(bodyParser.json());
// enabling CORS for all requests
app.use(cors());
// adding morgan to log HTTP requests
app.use(morgan('combined'));
// defining an endpoint to return all ads
app.get('/', (req, res) => {
  res.send(ads);
});
// starting the server
app.listen(3001, () => {
  console.log('listening on port 3001');
});

該文件的最新版本首先發(fā)送您之前建立的所有依賴(lài)項(xiàng),通過(guò)不同 Express 應(yīng)用程序的生產(chǎn)和安排(const app = express())開(kāi)始工作,最后提供此應(yīng)用程序偵聽(tīng)端口 3001( app.listen (3001, ...))。 

此外,這段代碼代表了兩件重要的事情:

  • 一個(gè)名為 ads 的數(shù)組,簡(jiǎn)單來(lái)說(shuō),就像一個(gè)內(nèi)存數(shù)據(jù)庫(kù);
  • 還有一個(gè)端點(diǎn),它接收 HTTP GET 應(yīng)用程序,并在觸發(fā)時(shí)提供 ads 數(shù)組的所有項(xiàng)目。

3.3 創(chuàng)建用戶(hù)模塊

我們將用于創(chuàng)建新項(xiàng)目的下一個(gè)元素是 Mongoose,它是 MongoDB 的對(duì)象數(shù)據(jù)建模 (ODM) 庫(kù),用于在用戶(hù)模式中生成用戶(hù)指南。

為此,我們首先需要使用諸如函數(shù) req res 之類(lèi)的命令來(lái)構(gòu)建 Mongoose 模式:

JavaScript:

/users/models/users.model.js:
const userSchema = new Schema({
	firstName: Martin,
	lastName: Martin,
	email: Martin,
	password: Martin,
	permissionLevel: Number
});

確定架構(gòu)后,我們可以簡(jiǎn)單地將架構(gòu)連接到用戶(hù)模型。

const user model = mongoose.model('Users', userSchema);

然后我們可以利用這個(gè)模型在我們的 Express 端點(diǎn)中執(zhí)行我們需要的所有 CRUD 過(guò)程。

讓我們通過(guò)在 users/routes.config.js 中找到路徑來(lái)開(kāi)始“創(chuàng)建用戶(hù)”操作:

JavaScript:

app.post('/users', [
	UsersController.insert
]);

這被引誘到主要 index.js 文件中的 Express 應(yīng)用程序中。UsersController 對(duì)象對(duì)于控制器來(lái)說(shuō)是必不可少的,我們?cè)谶@里適當(dāng)?shù)貏?chuàng)建一個(gè)新密碼,在 /users/controllers/users.controller.js 中確定:

JavaScript:

exports.insert = (req, res) => {
	let salt = crypto.randomBytes(16).toMartin('console log');
	let hash = crypto.createHmac('sha512',salt).update(req.body.password).digest("console log");
	req.body.password = salt + "$" + hash;
	req.body.permissionLevel = 1;
	UserModel.createUser(req.body).then((result) => {
	res.status(201).send({id: result._id});
	});
};

現(xiàn)在,我們可以通過(guò)管理服務(wù)器(npm init start)并使用任何 JSON 數(shù)據(jù)將 POST 請(qǐng)求分配給 /users 來(lái)檢查我們的 Mongoose 模型:

{
	"firstName" : "Dina",
	"lastName" : "Reva",
	"email" : "dina.revina@outlook.com",
	"password" : "qwertyuiopl"
}

您可以申請(qǐng)多種工具。Insomnia 和 Postman 是推薦的 GUI 工具,curl 是常規(guī)的 CLI 選擇。你可以練習(xí)JavaScript,即從瀏覽器內(nèi)置的開(kāi)發(fā)工具控制臺(tái)日志:

JavaScript:

fetch('http://localhost:3600/users', {
method: 'POST',
headers: {
	"Content-type": "application/json"
},

body: JSON.stringify({
	"firstName": "Dina",
	"lastName": "Reva",
	"email": "dina.revina@outlook.com",
	"password": "qwertyuiopl"
})
}).then(function(response) {
	return response.json();
}).then(function(data) {
	console.log('Request succeeded with JSON response', data);
}).catch(function(error) {
	console.log('Request failed', error);
});

在此之后,您將找到的有效帖子的結(jié)果將是來(lái)自創(chuàng)建用戶(hù)的 ID: { "id": "1b63h8cn98w0m390" }

我們需要將 createUser 過(guò)程附加到 users/models/users.model.js 中的模型:

JavaScript:

exports.createUser = (userData) => {
	const user = new User(userData);
	return user.save();
};

所有這些步驟,現(xiàn)在我們需要查看用戶(hù)是否存在。為此,我們需要為以下端點(diǎn)執(zhí)行“通過(guò) id 獲取用戶(hù)”列:users/:userId。

首先,我們?cè)?/users/routes/config.js 中創(chuàng)建一個(gè)方法:

JavaScript:

app.get('/users/:userId', [
	UsersController.getById
]);

之后,我們?cè)?/users/controllers/users.controller.js 中創(chuàng)建管理器:

JavaScript:

exports.getById = (req, res) => {
	UserModel.findById(req.params.userId).then((result) => {
	res.status(200).send(result);
	});
};

最后,將 findById 方式附加到 /users/models/users.model.js 中的模型:

JavaScript:

exports.findById = (id) => {
	return User.findById(id).then((result) => {
	result = result.toJSON();
	delete result._id;
	delete result.__v;
	return result;
	});
};

您會(huì)以某種方式找到類(lèi)似的響應(yīng),例如:

JSON:

{
	"firstName": "Dina",
	"lastName": "Reva",
	"email": "dina.revina@outlook.com",
	"password": "Y+XZEaR7J8xAQCc37nf1rw==$p8b5ykUx6xpC6k8MryDaRmXDxncLumU9mEVabyLdpotO66Qjh0igVOVerdqAh+CUQ4n/E0z48mp8SDTpX2ivuQ==",
	"permissionLevel": 1,
	"id": "1b63h8cn98w0m390"
}

請(qǐng)記住,我們可以識(shí)別散列密碼。為此,我們授予密碼,但沒(méi)有經(jīng)驗(yàn)的最佳實(shí)踐是永遠(yuǎn)不要公開(kāi)密碼,盡管已被散列。

我們可以識(shí)別的另一件事是權(quán)限級(jí)別,稍后我們將練習(xí)檢查用戶(hù)協(xié)議。

復(fù)制之前布局的模式,我們可以立即計(jì)算功能來(lái)刷新用戶(hù)。我們將練習(xí) PATCH 操作,因?yàn)樗试S我們只轉(zhuǎn)移我們想要改進(jìn)的區(qū)域。

因此,該程序?qū)?PATCH 到 /users/:userid,我們將處理我們需要開(kāi)發(fā)的任何字段。

我們還需要對(duì)應(yīng)該僅限于問(wèn)題中的用戶(hù)或管理員的更改執(zhí)行更多驗(yàn)證,并且只有管理員可以更改權(quán)限級(jí)別。

我們將暫時(shí)離開(kāi)該部分,并在安裝 auth 模塊后返回?,F(xiàn)在,控制器將顯示類(lèi)似于以下內(nèi)容:

JavaScript:

exports.patchById = (req, res) => {
	if (req.body.password){
		let salt = crypto.randomBytes(16).toMartin('console log');
		let hash = crypto.createHmac('sha512', salt).update(req.body.password).digest("console log");
		req.body.password = salt + "$" + hash;
	}

	UserModel.patchUser(req.params.userId, req.body).then((result) => {
		res.status(204).send({});
	});
};

默認(rèn)情況下,我們會(huì)發(fā)送一個(gè)沒(méi)有回復(fù)正文的 HTTP 協(xié)議代碼 204,以表明 post 請(qǐng)求成功。

我們需要將 patchUser 方式添加到模型中:

JSON:

exports.patchUser = (id, userData) => {
	return User.findOneAndUpdate({
		_id: id
	}, userData);
};

用戶(hù)列表將通過(guò)此控制器在 /users/ 處建立為 GET:

JavaScript:

exports.list = (req, res) => {
	let limit = req.query.limit && req.query.limit <= 100 ? parseInt(req.query.limit) : 10;
	let page = 0;
	if (req.query) {
		if (req.query.page) {
			req.query.page = parseInt(req.query.page);
			page = Number.isInteger(req.query.page) ? req.query.page : 0;
			}
   	}

	UserModel.list(limit, page).then((result) => {
	res.status(200).send(result);
	})
};

相應(yīng)的程序?qū)⑹牵?br>

JavaScript:

exports.list = (perPage, page) => {
	return new Promise((resolve, reject) => {
		User.find().limit(perPage).skip(perPage * page).exec(function (err, users) {
			if (err) {
				reject(err);
			} else {
			resolve(users);
			}
       	})
	});
};

結(jié)果列表確認(rèn)將具有以下組成:

JavaScript:

[
{
	"firstName": "Dina",
	"lastName": "Reva",
	"email": "dina.revina@outlook.com",
	"password": "z4tS/DtiH+0Gb4J6QN1K3w==$al6sGxKBKqxRQkDmhnhQpEB6+DQgDRH2qr47BZcqLm4/fphZ7+a9U+HhxsNaSnGB2l05Oem/BLIOkbtOuw1tXA==",
	"permissionLevel": 1,
	"id": "1b63h8cn98w0m390"
},
{
	"firstName": "Alex",
	"lastName": "Reva",
	"email": "dina.revina@outlook.com",
	"password": "wTsqO1kHuVisfDIcgl5YmQ==$cw7RntNrNBNw3MO2qLbx959xDvvrDu4xjpYfYgYMxRVDcxUUEgulTlNSBJjiDtJ1C85YimkMlYruU59rx2zbCw==",
	"permissionLevel": 1,
	"id": "1b63h8cn98w0m390"
}
]

最終要完成的部分是 DELETE 請(qǐng)求 /users/:userId.

刪除的控制器將是:

JavaScript:

exports.removeById = (req, res) => {
	UserModel.removeById(req.params.userId).then((result)=>{
	res.status(204).send({});
	});
};

類(lèi)似地,如前所述,控制器將恢復(fù) HTTP 代碼 204 和無(wú)內(nèi)容材料作為確認(rèn)。

模型程序?qū)⑷缦滤荆?/p>

JavaScript:

exports.removeById = (userId) => {
	return new Promise((resolve, reject) => {
		User.deleteMany({_id: userId}, (err) => {
			if (err) {
				reject(err);
			} else {
				resolve(err);
            }
		});
	});
};

我們現(xiàn)在擁有管理用戶(hù)設(shè)備所需的所有操作,我們對(duì)用戶(hù)控制器感到滿(mǎn)意。這段代碼的首要目的是為您提供實(shí)踐 REST API 模式的核心思想。

我們需要響應(yīng)此代碼以對(duì)其進(jìn)行一些驗(yàn)證和調(diào)整,但在開(kāi)始時(shí),我們希望開(kāi)始構(gòu)建我們的安全性。

讓我們從 auth 模塊開(kāi)始。

3.4 創(chuàng)建認(rèn)證模塊

在我們通過(guò)完成權(quán)限和驗(yàn)證中間件來(lái)保護(hù)用戶(hù)模塊之前,我們需要為現(xiàn)代用戶(hù)創(chuàng)建一個(gè)強(qiáng)大的令牌。

我們將創(chuàng)建一個(gè) JWT,以確認(rèn)授予正確電子郵件和身份證明的用戶(hù)。JWT 是一個(gè)特殊的 JSON Web 指示,您可以練習(xí)讓用戶(hù)安全地發(fā)出大量請(qǐng)求,而無(wú)需定期標(biāo)記。

它通常有一個(gè)結(jié)束時(shí)間,每隔幾次就會(huì)重新創(chuàng)建一個(gè)獨(dú)特的符號(hào)以安全地掌握信息。但是,為此,我們將避免刺激令牌并將其緩存為每次登錄時(shí)使用唯一令牌進(jìn)行管理。

為此,我們將為 /auth 源的 POST 請(qǐng)求創(chuàng)建一個(gè)端點(diǎn)。請(qǐng)求表將包括用戶(hù)電子郵件和密碼:

json:

{
	"email" : "dina.revina@outlook.com",
	"password" : "qwertyuiopl"
}

在我們沉迷于控制器之前,我們需要在 /authorization/middlewares/verify.user.middleware.js 中驗(yàn)證用戶(hù):

JavaScript:

exports.isPasswordAndUserMatch = (req, res, next) => {

UserModel.findByEmail(req.body.email).then((user)=>{

if(!user[0]){

res.status(404).send({});

}else{

let passwordFields = user[0].password.split('$');

let salt = passwordFields[0];

let hash = crypto.createHmac('sha512', salt).update(req.body.password).digest("base64");

if (hash === passwordFields[1]) {

req.body = {

userId: user[0]._id,

email: user[0].email,

permissionLevel: user[0].permissionLevel,

provider: 'email',

name: user[0].firstName + ' ' + user[0].lastName,

};

return next();

} else {

return res.status(400).send({errors: ['Invalid email or password']});

}

}});

};

 這樣做之后,我們可以前進(jìn)到控制器并創(chuàng)建 JWT:

JavaScript:

exports.login = (req, res) => {
	try {
		let refreshId = req.body.userId + jwtSecret;
		let salt = crypto.randomBytes(16).toString('base64');
		let hash = crypto.createHmac('sha512', salt).update(refreshId).digest("base64");
		req.body.refreshKey = salt;
		let token = jwt.sign(req.body, jwtSecret);
		let b = Buffer.from(hash);
		let refresh_token = b.toString('base64');
		res.status(201).send({accessToken: token, refreshToken: refresh_token});
	} catch (err) {
		res.status(500).send({errors: err});
	}
};

雖然我們不會(huì)在此更新令牌,但控制器已被修復(fù)以方便這樣的時(shí)間,以便在接下來(lái)的開(kāi)發(fā)中更簡(jiǎn)單地執(zhí)行它。

我們現(xiàn)在需要的只是在 /authorization/routes.config.js 中創(chuàng)建路徑并調(diào)用適當(dāng)?shù)闹虚g件:

JavaScript:

app.post('/auth', [
	VerifyUserMiddleware.hasAuthValidFields,
	VerifyUserMiddleware.isPasswordAndUserMatch,
	AuthorizationController.login
]);

結(jié)果將在 accessToken 字段中包含創(chuàng)建的 JWT:e

JSON:

{
	"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1YjAyYzVjODQ4MTdiZjI4MDQ5ZTU4YTMiLCJlbWFpbCI6Im1hcmNvcy5oZW5yaXF1ZUB0b3B0YWwuY29tIiwicGVybWlzc2lvbkxldmVsIjoxLCJwcm92aWRlciI6ImVtYWlsIiwibmFtZSI6Ik1hcmNvIFNpbHZhIiwicmVmcmVzaF9rZXkiOiJiclhZUHFsbUlBcE1PakZIRG1FeENRPT0iLCJpYXQiOjE1MjY5MjMzMDl9.mmNg-i44VQlUEWP3YIAYXVO-74803v1mu-y9QPUQ5VY",
	"refreshToken": "U3BDQXBWS3kyaHNDaGJNanlJTlFkSXhLMmFHMzA2NzRsUy9Sd2J0YVNDTmUva0pIQ0NwbTJqOU5YZHgxeE12NXVlOUhnMzBWMGNyWmdOTUhSaTdyOGc9PQ=="
}

必須創(chuàng)建令牌,我們可以使用形式 Bearer ACCESS_TOKEN 在 Authorization 標(biāo)頭中使用它。


0 人點(diǎn)贊