web api json
What a mouthful of a title. Wouldn’t you agree? In this walkthrough you’ll learn about securing your Serverless endpoints with JSON web tokens.
這么大的頭銜。 你不同意嗎? 在本演練中,您將學習如何使用JSON Web令牌保護無服務器端點。
This will include a basic setup of a Serverless REST API with a few endpoints, and of course an authorizer function. This authorizer will act as the middleware for authorizing access to your resources.
這將包括具有幾個端點的無服務器REST API的基本設置,當然還有授權者功能。 該授權者將充當授權訪問您的資源的中間件。
During the creation process, we’ll use the Serverless framework for simulating a development environment just like you’re used to. Wrapping up the guide we’ll also set up a monitoring tool called Dashbird. It will allow us to simulate the debugging capabilities and overview of a regular Node.js application in a way that’s natural and easy to comprehend. It also has a free tier and doesn’t require a credit card to set up.
在創建過程中,我們將像您一樣使用Serverless框架來模擬開發環境。 在編寫指南的同時,我們還將建立一個名為Dashbird的監視工具。 這將使我們能夠以自然且易于理解的方式模擬調試功能和常規Node.js應用程序的概述。 它還有一個免費套餐,不需要信用卡即可設置。
If anything I just mentioned above is new to you, don’t worry. I’ll explain it all below. Otherwise you can freshen up your knowledge by taking a look at these tutorials:
如果我上面剛剛提到的任何東西對您來說都不新鮮,請不要擔心。 我將在下面解釋所有內容。 否則,您可以通過閱讀以下教程來增強知識:
Securing Node.js RESTful APIs with JWT — Authentication and Authorization explained.
使用JWT保護Node.js RESTful API的安全 -解釋了身份驗證和授權。
A crash course on Serverless with Node.js— Serverless basics explained.
使用Node.js的 Serverless 速成課程 —解釋了Serverless的基礎知識。
Building a Serverless REST API with Node.js and MongoDB — Serverless REST APIs explained.
使用Node.js和MongoDB構建無服務器REST API —說明了無服務器REST API。
TL; DR (TL;DR)
Before jumping in head first, you can severely hurt my feelings and only read this TL;DR. Or, continue reading the whole article. ?
在先跳頭之前,您可能會嚴重傷害我的感情,僅閱讀此TL; DR。 或者,繼續閱讀全文。 ?
Creating the API
創建API
-
--
Adding a database
添加數據庫
-
--
Adding the functions
添加功能
-
--
Adding business logic for the users
為用戶添加業務邏輯
-
--
Adding the authentication
添加身份驗證
-
--
Adding the authorization
添加授權
Deployment
部署方式
Testing
測試中
Monitoring
監控方式
Ready? Let’s jump in!
準備? 讓我們跳進去!
創建API (Creating the API)
First of all, we need to set up the Serverless framework for our local development environment. This framework is the de facto framework for all things related to Serverless architectures. Jump over to their site and follow the instructions to set it up, or reference back to the article I linked above.
首先,我們需要為本地開發環境設置無服務器框架。 該框架是與無服務器架構有關的所有事物的事實上的框架。 跳轉到他們的網站并按照說明進行設置,或者參考上面我鏈接的文章 。
The installation process is incredibly simple. You set up an AWS management role in your AWS account, and link it to your installation of the Serverless framework. The actual installation process is just running one simple command.
安裝過程非常簡單。 您在您的AWS賬戶中設置了一個AWS管理角色,并將其鏈接到您的無服務器框架的安裝。 實際的安裝過程只是運行一個簡單的命令。
Fire up a terminal window and run the command below.
啟動終端窗口并運行以下命令。
$ npm install -g serverless
Moving on, once you have it installed, there’s only one more command to run in the terminal to get a boilerplate Serverless service on your local development machine.
繼續,一旦安裝完畢,在終端中只需要再運行一個命令即可在本地開發計算機上獲得樣板的無服務器服務。
$ sls create -t aws-nodejs -p api-with-auth
The command above will generate the boilerplate code you need.
上面的命令將生成您所需的樣板代碼。
Change to the newly created directory called api-with-auth
and open it up with your code editor of choice.
轉到新創建的名為api-with-auth
目錄,然后使用您選擇的代碼編輯器將其打開。
$ cd api-with-auth
Once open, you’ll see two main files. A handler.js
and a serverless.yml
file. The handler.js
contains our app logic while the serverless.yml
defines our resources.
打開后,您將看到兩個主要文件。 一個handler.js
和一個serverless.yml
文件。 handler.js
包含我們的應用程序邏輯,而serverless.yml
定義了我們的資源。
Now it’s time to install some dependencies in order to set up our needed authentication/authorization methods, password encryption and ORM for the database interaction.
現在該安裝一些依賴項,以設置我們所需的身份驗證/授權方法,密碼加密和數據庫交互的ORM。
$ npm init -y$ npm install --save bcryptjs bcryptjs-then jsonwebtoken mongoose
There’s what we need for production, but for development we’ll grab the Serverless Offline plugin.
這是生產所需的,但是對于開發,我們將獲取Serverless Offline插件。
$ npm install --save-dev serverless-offline
Lovely!
可愛!
添加數據庫 (Adding a database)
For the persistent data store, we’ll just grab a hosted MongoDB instance on MongoDB Atlas. Here’s a reference for an article where I explained it in detail.
對于持久性數據存儲,我們只需在MongoDB Atlas上獲取托管的MongoDB實例。 這是我詳細解釋文章的參考。
In the root of the service folder let’s create a db.js
file to keep our logic for the database connection. Go ahead and paste in this snippet of code.
在服務文件夾的根目錄中,我們創建一個db.js
文件來保留數據庫連接的邏輯。 繼續并粘貼此代碼段。
This is a rather simple implementation of establishing a database connection if no connection exists. But, if it exists, I’ll use the already established connection. You see the process.env.DB
? We'll use a custom secrets.json
file to keep our private keys out of GitHub by adding it to the .gitignore
. This file will then be loaded in the serverless.yml
. Actually, let's do that now.
如果不存在連接,這是建立數據庫連接的相當簡單的實現。 但是,如果存在,我將使用已經建立的連接。 您看到了process.env.DB
嗎? 我們將使用自定義的secrets.json
文件,通過將其添加到.gitignore
來將私鑰保留在GitHub之外。 然后,該文件將被加載到serverless.yml
。 實際上,讓我們現在開始。
Add your MongoDB connection string to the db
field.
將您的MongoDB連接字符串添加到db
字段。
With this file created, let’s move on to the serverless.yml
. Open it up and delete all the boilerplate code so we can start fresh. Then, go ahead and paste this in.
創建此文件后,讓我們繼續到serverless.yml
。 打開它并刪除所有樣板代碼,以便我們重新開始。 然后,繼續粘貼。
As you can see, it’s just a simple setup configuration. The custom
section tells the main configuration to grab values from a secrets.json
file. We'll add that file to the .gitignore
because pushing private keys to GitHub is a mortal sin punishable by death! Not really, but still, don't push keys to GitHub. Seriously, please don't.
如您所見,這只是一個簡單的設置配置。 custom
部分告訴主配置從secrets.json
文件中獲取值。 我們將該文件添加到.gitignore
因為將私鑰推送到GitHub是一種致命罪,應處以死刑! 并非如此,但仍然不要將鍵推到GitHub。 說真的,請不要。
添加功能 (Adding the functions)
Just a tiny bit of configuring left to do before jumping into the business logic! We need to add the function definitions in the serverless.yml
right below the providers section we added above.
在跳入業務邏輯之前,只需要進行一點點配置即可! 我們需要在上面添加的providers部分下面的serverless.yml
添加函數定義。
There are a total of five functions.
一共有五個功能。
The
VerifyToken.js
will contain an.auth
method for checking the validity of the JWT passed along with the request to the server. This will be our authorizer function. The concept of how an authorizer works is much like how a middleware works in plain old basic Express.js. Just a step between the server receiving the request and handling data to be sent back to the client.VerifyToken.js
將包含一個.auth
方法,用于檢查與請求一起傳遞給服務器的JWT的有效性。 這將是我們的授權者功能。 授權者的工作原理很像中間件在普通的基本Express.js中的工作方式。 在服務器接收請求和處理要發送回客戶端的數據之間的一個步驟。The
login
andregister
functions will do the basic user authentication. We'll add business logic for those in theAuthHandler.js
file.login
和register
功能將執行基本的用戶身份驗證。 我們將在AuthHandler.js
文件中添加業務邏輯。However, the
me
function will respond with the current authenticated user based on the provided JWT token. Here's where we'll use the authorizer function.但是,
me
函數將基于提供的JWT令牌與當前經過身份驗證的用戶進行響應。 這是我們使用授權者功能的地方。The
getUsers
function is just a generic public API for fetching registered users from the database.getUsers
函數只是用于從數據庫中獲取注冊用戶的通用公共API。
From the serverless.yml
file above you can make out a rough project structure. To make it clearer, take a look at the image above.
從上面的serverless.yml
文件中,您可以得出一個大致的項目結構。 為了更加清晰,請看上圖。
Makes a bit more sense now? Moving on, let’s add the logic for fetching users.
現在更有意義了嗎? 繼續,讓我們添加獲取用戶的邏輯。
為用戶添加業務邏輯 (Adding business logic for the users)
Back in your code editor, delete the handler.js
file and create a new folder, naming it user
. Here you'll add a User.js
file for the model, and a UserHandler.js
for the actual logic.
返回代碼編輯器,刪除handler.js
文件并創建一個新文件夾,將其命名為user
。 在這里,您將添加一個User.js
文件的模型和UserHandler.js
的實際邏輯。
Pretty straightforward if you’ve written a Node app before. We require Mongoose, create the schema, add it to Mongoose as a model, finally exporting it for use in the rest of the app.
如果您之前編寫過Node應用程序,則非常簡單。 我們需要Mongoose,創建架構,將其作為模型添加到Mongoose,最后將其導出以在應用程序的其余部分中使用。
Once the model is done, it’s time to add basic logic.
模型完成后,就該添加基本邏輯了。
This is a bit tricky to figure out when you see it for the first time. But let’s start from the top.
第一次看到時很難弄清楚。 但是,讓我們從頭開始。
By requiring the db.js
we have access to the database connection on MongoDB Atlas. With our custom logic for checking the connection, we've made sure not to create a new connection once one has been established.
通過要求db.js
我們可以訪問MongoDB Atlas上的數據庫連接。 利用我們用于檢查連接的自定義邏輯,我們確保一旦建立了連接就不會創建新連接。
The getUsers
helper function will only fetch all the users, while the module.exports.getUsers
Lambda function will connect to the database, run the helper function, and return the response back to the client. This is more than enough for the UserHandler.js
. The real fun starts with the AuthProvider.js
.
getUsers
幫助器函數將僅獲取所有用戶,而module.exports.getUsers
Lambda函數將連接到數據庫,運行幫助器函數,并將響應返回給客戶端。 對于UserHandler.js
,這UserHandler.js
。 真正的樂趣始于AuthProvider.js
。
添加身份驗證 (Adding the authentication)
In the root of your service, create a new folder called auth
. Add a new file called AuthHandler.js
. This handler will contain the core authentication logic for our API. Without wasting any more time, go ahead and paste this snippet into the file. This logic will enable user registration, saving the user to the database and returning a JWT token to the client for storing in future requests.
在服務的根目錄中,創建一個名為auth
的新文件夾。 添加一個名為AuthHandler.js
的新文件。 該處理程序將包含我們API的核心身份驗證邏輯。 不要浪費更多的時間,繼續并將此代碼段粘貼到文件中。 該邏輯將啟用用戶注冊,將用戶保存到數據庫中,并將JWT令牌返回給客戶端以存儲在將來的請求中。
First we require the dependencies, and add the module.exports.register
function. It's pretty straightforward. We're once again connecting to the database, registering the user and sending back a session object which will contain a JWT token. Take a closer look at the local register()
function, because we haven't declared it yet. Bare with me a few more seconds, we’ll get to it in a moment.
首先,我們需要依賴項,并添加module.exports.register
函數。 這很簡單。 我們再次連接到數據庫,注冊用戶并發送回包含JWT令牌的會話對象。 請仔細查看本地register()
函數,因為我們尚未對其進行聲明。 再等我幾秒鐘,我們待會兒處理。
With the core structure set up properly, let’s begin with adding the helpers. In the same AuthHandler.js
file go ahead and paste this in as well.
在正確設置核心結構之后,讓我們開始添加助手。 在同一AuthHandler.js
文件中,繼續并將其粘貼。
We’ve created three helper functions for signing a JWT token, validating user input, and creating a user if they do not already exist in our database. Lovely!
我們創建了三個幫助器函數,用于對JWT令牌進行簽名,驗證用戶輸入以及在數據庫中尚不存在的情況下創建用戶。 可愛!
With the register()
function completed, we still have to add the login()
. Add the module.exports.login
just below the functions comment.
完成register()
函數后,我們仍然必須添加login()
。 在功能注釋下方添加module.exports.login
。
Once again we have a local function, this time named login()
. Let's add that as well under the helpers comment.
再一次,我們有一個本地函數,這次命名為login()
。 我們還要在助手注釋下添加它。
Awesome! We’ve added the helpers as well. With that, we’ve added authentication to our API. As easy as that. Now we have a token-based authentication model with the possibility of adding authorization. That’ll be our next step. Hang on!
太棒了! 我們也添加了助手。 這樣,我們就向API添加了身份驗證 。 就這么簡單。 現在,我們有了一個基于令牌的身份驗證模型,可以添加授權。 那將是我們的下一步。 不掛斷!
添加授權 (Adding the authorization)
With the addition of a VerifyToken.js
file, we can house all the authorization logic as a separate middleware. Very handy if we want to keep separation of concerns. Go ahead and create a new file called VerifyToken.js
in the auth
folder.
通過添加VerifyToken.js
文件,我們可以將所有授權邏輯作為單獨的中間件存放。 如果我們要保持關注點分離,非常方便。 繼續,在auth
文件夾中創建一個名為VerifyToken.js
的新文件。
We have a single function exported out of the file, called module.exporst.auth
with the usual three parameters. This function will act as a middleware. If you're familiar with Node.js you'll know what a middleware is, otherwise, check this out for a more detailed explanation.
我們從文件中導出了一個函數,稱為module.exporst.auth
具有通常的三個參數。 此功能將充當中間件 。 如果你熟悉Node.js的,你就會知道中間件是什么,否則,檢查這出了更詳細的解釋。
The authorizationToken
, our JWT, will be passed to the middleware through the event. We're just assigning it to a local constant for easier access.
我們的JWT的authorizationToken
將通過該事件傳遞給中間件。 我們只是將其分配給本地常量,以便于訪問。
All the logic here is just to check whether the token is valid and send back a generated policy by calling the generatePolicy
function. This function is required by AWS, and you can grab it from various docs on AWS and from the Serverless Framework examples GitHub page.
這里的所有邏輯只是檢查令牌是否有效,并通過調用generatePolicy
函數將生成的策略發送回去。 AWS要求此功能,您可以從AWS上的各種文檔以及無服務器框架示例GitHub頁面中獲取 。
It’s important because we pass along the decoded.id
along in the callback
. Meaning, the next Lambda Function which sits behind our VerifyToken.auth
authorizer function will have access to the decoded.id
in its event
parameter. Awesome, right!?
這很重要,因為我們在callback
傳遞了decoded.id
。 意思是,位于我們的VerifyToken.auth
授權者函數后面的下一個Lambda函數將可以訪問其event
參數中的decoded.id
。 太好了,對!!
Once we have the token verification completed, all that’s left if to add a route to sit behind the authorizer function. For the sake of simplicity, let’s add a /me
route to grab the currently logged user based on the JWT passed along the GET
request.
一旦我們完成了令牌驗證,剩下的就是添加一條添加到授權者函數后面的路由。 為了簡單起見,讓我們添加一個/me
路由,以基于GET
請求傳遞的JWT來捕獲當前登錄的用戶。
Jump back to the AuthHandler.js
file and paste this in.
跳回到AuthHandler.js
文件并將其粘貼。
Awesome! The last Lambda Function we’ll add in this tutorial will be module.exports.me
. It'll just grab the userId
passed from the authorizer and call the me
helper function while passing in the userId
. The me
function will grab the user from the database and return it back. All the module.exports.me
Lambda does is just retrieves the currently authenticated user. But, the endpoint is protected, meaning only a valid token can access it.
太棒了! 我們將在本教程中添加的最后一個Lambda函數將是module.exports.me
。 它只會抓住userId
從授權通過,并調用me
助手功能,同時通過在userId
。 me
函數將從數據庫中抓取用戶并將其返回。 Lambda所做的所有module.exports.me
只是檢索當前經過身份驗證的用戶。 但是,端點是受保護的,這意味著只有有效的令牌才能訪問它。
Great work following along so far, let’s deploy it so we can do some testing.
到目前為止,我們將繼續進行出色的工作,讓我們進行部署,以便進行一些測試。
部署方式 (Deployment)
Hopefully, you’ve configured your AWS account to work with the Serverless Framework. If you have, there’s only one command to run, and you’re set.
希望您已將您的AWS賬戶配置為可與無服務器框架一起使用。 如果有的話,只有一個命令可以運行,并且已經設置好。
$ sls deploy
Voila! Wait for it to deploy, and start enjoying your Serverless API with JWT authentication and authorization.
瞧! 等待它部署,然后開始使用帶有JWT身份驗證和授權的無服務器API。
You’ll get a set of endpoints sent back to you in the terminal once the functions have been deployed. We’ll be needing those in the next section.
部署功能后,您將在終端中收到一組端點發送回給您。 在下一節中,我們將需要這些。
測試中 (Testing)
The last step in any development process should ideally be making sure it all works like it should. This is no exception. One of the two tools I use for testing my endpoints is Insomnia. So, I’ll go ahead and open it up. But, you can use Postman, or any other tool you like.
理想情況下,任何開發過程的最后一步都應該確保所有工作都按預期進行。 也不例外。 我用于測試端點的兩個工具之一是Insomnia 。 因此,我將繼續打開它。 但是,您可以使用Postman或任何您喜歡的其他工具。
Note: If you want to start by testing everything locally, be my guest. You can always use serverless-offline.
注意 :如果您想從本地進行所有測試,請成為我的客人。 您始終可以使用serverless-offline 。
In your terminal, run a simple command:
在您的終端中,運行一個簡單的命令:
$ sls offline start --skipCacheInvalidation
But I like to go hardcore! Let’s test directly on the deployed endpoints.
但是我喜歡成為鐵桿! 讓我們直接在部署的端點上進行測試。
Starting slow, first hit the /register
endpoint with a POST
request. Make sure to send the payload as JSON. Hit Send and you'll get a token back! Nice, just what we wanted.
起步緩慢,首先使用POST
請求命中/register
端點。 確保將有效負載作為JSON發送。 點擊發送 ,您將獲得令牌! 很好,正是我們想要的。
Copy the token and now hit the /me
endpoint with a GET
request. Don't forget to add the token in the headers with the Authorization
key.
復制令牌,然后使用GET
請求訪問/me
端點。 不要忘記使用Authorization
密鑰在標頭中添加令牌。
You’ll get the current user sent back to you. And there it is. Lovely.
您會把當前用戶發回給您。 在那里。 可愛。
Just to make sure the other endpoints work as well, go ahead and hit the /login
endpoint with the same credentials as with the /register
endpoint you hit just recently.
為了確保其他端點也正常工作,請繼續使用與最近/login
的/register
端點相同的憑據來命中/login
端點。
Does it work? Of course it does. There we have it, a fully functional authentication and authorization system implemented in a Serverless environment with JWT and Authorizers. All that’s left is to add a way to monitor everything.
它行得通嗎? 當然可以。 我們擁有一個在JWT和Authorizers的無服務器環境中實現的功能齊全的身份驗證和授權系統。 剩下的就是添加一種監視所有內容的方法。
監控方式 (Monitoring)
I usually monitor my Lambdas with Dashbird. It’s been working great for me so far. My point for showing you this is for you too see the console logs from the Lambda Function invocations. They’ll show you when the Lambda is using a new or existing database connection. Here’s what the main dashboard looks like, where I see all my Lambdas and their stats.
我通常使用Dashbird監視Lambda。 到目前為止,對我來說一直很好。 向我展示這一點是因為您也可以從Lambda函數調用中看到控制臺日志。 當Lambda使用新的或現有的數據庫連接時,它們將向您顯示。 這是主儀表板的外觀,在這里我可以查看所有Lambda及其統計信息。
Pressing on one of the Lambda Functions, let’s say register, you’ll see the logs for that particular function. The bottom will show a list of invocations for the function. You can even see which were crashes and cold starts.
按下Lambda函數之一,即注冊 ,您將看到該特定函數的日志。 底部將顯示該函數的調用列表。 您甚至可以查看哪些是崩潰和冷啟動。
Pressing on the cold start invocation will take you to the invocation page and you’ll see a nice log which says => using new database connect
ion.
按下冷啟動調用將帶您進入調用頁面,您將看到一個漂亮的日志,其中顯示=> using new database connect
。
Now backtrack a bit, and pick one of the invocations which is not a cold start. Checking the logs for this invocation will show you => using existing database connect
ion.
現在回溯一下,然后選擇一個調用,這不是一個冷門。 檢查此調用的日志將顯示=> using existing database connect
。
Nice! You have proper insight into your system!
真好! 您對系統有適當的了解!
結語 (Wrapping up)
Amazing what you can do with a few nice tools. Creating a REST API with authentication and authorization is made simple with Serverless, JWT, MongoDB, and Dashbird. Much of the approach to this tutorial was inspired by some of my previous tutorials. Feel free to check them out below.
使用一些不錯的工具,您可以做什么。 使用Serverless ,JWT,MongoDB和Dashbird可以輕松創建具有身份驗證和授權的REST API。 本教程的許多方法都受到我以前的一些教程的啟發。 請隨時在下面查看它們。
Adnan Rahi? - MediumRead writing from Adnan Rahi? on Medium. Co-founder @bookvar_co. Teacher @ACADEMY387. Author @PacktPub. Campsite leader…medium.com
AdnanRahi?-中 閱讀AdnanRahi?在Medium上的寫作。 聯合創始人@bookvar_co。 老師@ ACADEMY387。 作者@PacktPub。 營地負責人… medium.com
The approach of using authorizers to simulate middleware functions is incredibly powerful for securing your Serverless APIs. It’s a technique I use on a daily basis. Hopefully you’ll find it of use in your future endeavors as well!
使用授權者來模擬中間件功能的方法對于保護無服務器API的功能非常強大。 我每天都使用這項技術。 希望您在以后的工作中也會發現它的用處!
If you want to take a look at all the code we wrote above, here’s the repository. Or if you want to dig deeper into the lovely world of Serverless, have a look at all the tools I mentioned above, or check out a course I authored.
如果您想看一下我們上面編寫的所有代碼, 這里是存儲庫 。 或者,如果您想深入研究Serverless的美好世界,請查看我上面提到的所有工具,或者查看我編寫的課程 。
Hope you guys and girls enjoyed reading this as much as I enjoyed writing it. Do you think this tutorial will be of help to someone? Do not hesitate to share. If you liked it, smash the clap below so other people will see this here on Medium.
希望你們和我喜歡寫這本書一樣喜歡閱讀。 您認為本教程對某人有幫助嗎? 不要猶豫,分享。 如果您喜歡它,請粉碎 下面 的 拍手 ,以便其他人可以在Medium上看到。
翻譯自: https://www.freecodecamp.org/news/a-crash-course-on-securing-serverless-apis-with-json-web-tokens-ff657ab2f5a5/
web api json