

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 教學課程：為 建立自訂授權方 AWS IoT Core
<a name="custom-auth-tutorial"></a>

本教學課程示範使用 AWS CLI來建立、驗證和使用自訂身分驗證的步驟。使用本教學課程，您可以選擇性地使用 Postman，藉由使用 HTTP 發佈 API 將資料傳送到 AWS IoT Core 。

本教學課程會向您展示如何建立範例 Lambda 函數，搭配使用 **create-authorizer** 呼叫與啟用的字符簽署，以實作授權和身分驗證邏輯，以及自訂授權方。然後，使用 驗證授權方**test-invoke-authorizer**，最後您可以使用 HTTP 發佈 API AWS IoT Core 將資料傳送至測試 MQTT 主題。範例請求將使用 `x-amz-customauthorizer-name` 標頭指定要叫用的授權方，並以請求標頭傳遞 token-key-name 和 `x-amz-customauthorizer-signature`。

**您會在本教學課程中學到什麼：**
+ 如何將 Lambda 函數建立為自訂授權方處理常式
+ 如何使用啟用字符簽署 AWS CLI 的 建立自訂授權方
+ 如何使用 **test-invoke-authorizer** 命令測試您的自訂授權方
+ 如何使用[Postman](https://www.postman.com/) 發佈 MQTT 主題，以及如何利用您的自訂授權方驗證請求

此教學課程約需 60 分鐘方能完成。

**Topics**
+ [步驟 1：為自訂授權方建立 Lambda 函數](#custom-auth-tutorial-define)
+ [步驟 2：為自訂授權方建立公有和私有金鑰對](#custom-auth-tutorial-keys)
+ [步驟 3：建立自訂授權方資源及其授權](#custom-auth-tutorial-authorizer)
+ [步驟 4：呼叫 test-invoke-authorizer 來測試授權方](#custom-auth-tutorial-test)
+ [步驟 5：使用 Postman 測試發佈 MQTT 郵件](#custom-auth-tutorial-postman)
+ [步驟 6：在 MQTT 測試用戶端中檢視訊息](#custom-auth-tutorial-testclient)
+ [步驟 7：檢閱結果及後續步驟](#custom-auth-tutorial-review)
+ [步驟 8：清理](#custom-auth-tutorial-cleanup)

**開始本教學課程之前，請確定您有：**
+ 

**[設定 AWS 帳戶](setting-up.md)**  
您需要 AWS 帳戶 和 AWS IoT 主控台才能完成本教學課程。

  當您用於本教學課程的帳戶至少包含這些 AWS 受管政策時，此帳戶最適用：
  + [https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/IAMFullAccess$jsonEditor](https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/IAMFullAccess$jsonEditor)
  + [https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/AWSIoTFullAccess$jsonEditor](https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/AWSIoTFullAccess$jsonEditor)
  + [https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/AWSLambda_FullAccess$jsonEditor](https://console.aws.amazon.com//iam/home#/policies/arn:aws:iam::aws:policy/AWSLambda_FullAccess$jsonEditor)
**重要**  
本教學課程中使用的 IAM 政策比您應該在生產實作中遵循的 IAM 政策更寬鬆。在生產環境中，請確定您的帳戶和資源策略僅授予必要的許可。  
當您建立 IAM 政策進行生產時，請判斷使用者和角色需要哪些存取權，然後設計政策，讓使用者只能執行這些任務。  
如需詳細資訊，請參閱 [IAM 中的安全最佳實務](https://docs.aws.amazon.com//IAM/latest/UserGuide/best-practices.html)。
+ 

**已安裝 AWS CLI**  
如需如何安裝 的資訊 AWS CLI，請參閱[安裝 AWS CLI](https://docs.aws.amazon.com//cli/latest/userguide/cli-chap-install.html)。本教學課程需要 AWS CLI 版本 `aws-cli/2.1.3 Python/3.7.4 Darwin/18.7.0 exe/x86_64` 或更新版本。
+ 

**OpenSSL 工具**  
本教學課程中的範例使用 [LibreSSL 2.6.5](https://www.libressl.org/)。您也可以針對本教學課程使用 [OpenSSL v1.1.1i](https://www.openssl.org/) 工具。
+ 

**檢閱了 [AWS Lambda](https://docs.aws.amazon.com//lambda/latest/dg/welcome.html) 概觀**  
如果您 AWS Lambda 未曾使用過 ，請檢閱[AWS Lambda](https://docs.aws.amazon.com//lambda/latest/dg/welcome.html)和[開始使用 Lambda](https://docs.aws.amazon.com//lambda/latest/dg/getting-started.html) 以了解其術語和概念。
+ 

**已檢閱如何在 Postman 中建置請求**  
如需詳細資訊，請參閱[建置請求](https://learning.postman.com/docs/sending-requests/requests/)。
+ 

**已從前一個教學課程中移除自訂授權方**  
您的 一次 AWS 帳戶 只能設定有限數量的自訂授權方。如需如何移除自訂授權方的相關資訊，請參閱 [步驟 8：清理](#custom-auth-tutorial-cleanup)。

## 步驟 1：為自訂授權方建立 Lambda 函數
<a name="custom-auth-tutorial-define"></a>

中的自訂身分驗證 AWS IoT Core 會使用您建立的授權[方資源](https://docs.aws.amazon.com//iot/latest/apireference/API_AuthorizerDescription.html)來驗證和授權用戶端。您將在本節中建立的 函數會在用戶端連線至 和存取 AWS IoT 資源時，進行身分驗證 AWS IoT Core 和授權。

Lambda 函數會執行下列動作：
+ 如果請求來自 **test-invoke-authorizer**，它會傳回一個具有 `Deny` 動作的 IAM 政策。
+ 如果請求來自使用 HTTP 的 Postman，且 `actionToken` 參數的值為 `allow`，則會傳回具有 `Allow`動作的 IAM 政策。否則，它會傳回一個具有 `Deny` 動作的 IAM 政策。

**若要為自訂授權方建立 Lambda 函數**

1. 在 [Lambda](https://console.aws.amazon.com//lambda/home#) 主控台中，開啟 [Functions](https://console.aws.amazon.com//lambda/home#/functions) (函數)。

1. 選擇**建立函數**。

1. 確認已選取 **Author from scratch** (從頭開始撰寫)。

1. 在 **Basic information** (基本資訊) 下：

   1. 在**函數名稱** 中，輸入 **custom-auth-function**。

   1. 在**執行期**中，確認 **Node.js 18.x** 

1. 選擇**建立函數**。

   Lambda 會建立 Node.js 函數和許可函數上傳記錄的[執行角色](https://docs.aws.amazon.com//lambda/latest/dg/lambda-intro-execution-role.html)。當您叫用函數時，Lambda 函數會擔任執行角色，並使用執行角色來建立 AWS SDK 的登入資料，以及從事件來源讀取資料。

1. 若要在 [AWS Cloud9](https://docs.aws.amazon.com/cloud9/latest/user-guide/welcome.html) 編輯器中查看函數的程式碼和組態，請在設計工具視窗中選擇 **custom-auth-function**，然後在編輯器的導覽窗格中選擇 **index.js**。

   對於指令碼語言 (例如 Node.js)，Lambda 包含可傳回成功回應的基本函數。您可以使用 [AWS Cloud9](https://docs.aws.amazon.com/cloud9/latest/user-guide/welcome.html) 編輯器來編輯函數，只要原始碼不超過 3 MB。

1. 將編輯器中的 **index.js** 程式碼取代為下列程式碼：

   ```
   // A simple Lambda function for an authorizer. It demonstrates
   // How to parse a CLI and Http password to generate a response.
   
   export const handler = async (event, context, callback) => {
   
       //Http parameter to initiate allow/deny request
       const HTTP_PARAM_NAME='actionToken';
       const ALLOW_ACTION = 'Allow';
       const DENY_ACTION = 'Deny';
   
       //Event data passed to Lambda function
       var event_str = JSON.stringify(event);
       console.log('Complete event :'+ event_str);
   
       //Read protocolData from the event json passed to Lambda function
       var protocolData = event.protocolData;
       console.log('protocolData value---> ' + protocolData);
   
       //Get the dynamic account ID from function's ARN to be used
       // as full resource for IAM policy
       var ACCOUNT_ID = context.invokedFunctionArn.split(":")[4];
       console.log("ACCOUNT_ID---"+ACCOUNT_ID);
   
       //Get the dynamic region from function's ARN to be used
       // as full resource for IAM policy
       var REGION = context.invokedFunctionArn.split(":")[3];
       console.log("REGION---"+REGION);
   
       //protocolData data will be undefined if testing is done via CLI.
       // This will help to test the set up.
       if (protocolData === undefined) {
   
           //If CLI testing, pass deny action as this is for testing purpose only.
           console.log('Using the test-invoke-authorizer cli for testing only');
           callback(null, generateAuthResponse(DENY_ACTION,ACCOUNT_ID,REGION));
   
       } else{
   
           //Http Testing from Postman
           //Get the query string from the request
           var queryString = event.protocolData.http.queryString;
           console.log('queryString values -- ' + queryString);
           /*         global URLSearchParams       */
           const params = new URLSearchParams(queryString);
           var action = params.get(HTTP_PARAM_NAME);
   
           if(action!=null && action.toLowerCase() === 'allow'){
   
               callback(null, generateAuthResponse(ALLOW_ACTION,ACCOUNT_ID,REGION));
   
           }else{
   
               callback(null, generateAuthResponse(DENY_ACTION,ACCOUNT_ID,REGION));
   
           }
   
       }
   
   };
   
   // Helper function to generate the authorization IAM response.
   var generateAuthResponse = function(effect,ACCOUNT_ID,REGION) {
   
       var full_resource = "arn:aws:iot:"+ REGION + ":" + ACCOUNT_ID + ":*";
       console.log("full_resource---"+full_resource);
   
       var authResponse = {};
       authResponse.isAuthenticated = true;
       authResponse.principalId = 'principalId';
   
       var policyDocument = {};
       policyDocument.Version = '2012-10-17';		 	 	 
       policyDocument.Statement = [];
       var statement = {};
       statement.Action = 'iot:*';
       statement.Effect = effect;
       statement.Resource = full_resource;
       policyDocument.Statement[0] = statement;
       authResponse.policyDocuments = [policyDocument];
       authResponse.disconnectAfterInSeconds = 3600;
       authResponse.refreshAfterInSeconds = 600;
   
       console.log('custom auth policy function called from http');
       console.log('authResponse --> ' + JSON.stringify(authResponse));
       console.log(authResponse.policyDocuments[0]);
   
       return authResponse;
   }
   ```

1. 選擇**部署**。

1. 在 **Changes deployed** (已部署變更) 出現在編輯器上方之後：

   1. 捲動至編輯器上方的 **Function overview** (函數概觀) 區段。

   1. 複製 **Function ARN** (函數 ARN) 並加以儲存，以便稍後可在本教學課程中使用。

1. 測試您的函數

   1. 選擇 **Test** (測試) 標籤。

   1. 使用預設測試設定，選擇 **Invoke** (叫用)。

   1. 如果測試成功，請在 **Execution results** (執行結果) 下，開啟 **Details** (詳細資訊) 檢視。您應該會看到函數傳回的政策文件。

      如果測試失敗或看不到政策文件，請檢閱程式碼以尋找並更正錯誤。

## 步驟 2：為自訂授權方建立公有和私有金鑰對
<a name="custom-auth-tutorial-keys"></a>

您的自訂授權方需要公有和私有金鑰來驗證它。本節中的命令會使用 OpenSSL 工具來建立此金鑰對。

**若要為自訂授權方建立公有和私有金鑰對**

1. 建立私有金鑰檔案。

   ```
   openssl genrsa -out private-key.pem 4096
   ```

1. 驗證您剛建立的私有金鑰檔案。

   ```
   openssl rsa -check -in private-key.pem -noout
   ```

   如果命令未顯示任何錯誤，則私有金鑰檔案是有效的。

1. 建立公有金鑰檔案。

   ```
   openssl rsa -in private-key.pem -pubout -out public-key.pem
   ```

1. 驗證公有金鑰檔案。

   ```
   openssl pkey -inform PEM -pubin -in public-key.pem -noout
   ```

   如果命令未顯示任何錯誤，則公有金鑰檔案是有效的。

## 步驟 3：建立自訂授權方資源及其授權
<a name="custom-auth-tutorial-authorizer"></a>

 AWS IoT 自訂授權方是將先前步驟中建立的所有元素連結在一起的資源。在本節中，您將建立自訂授權方資源，並許可其執行您先前建立的 Lambda 函數。您可以使用 AWS IoT 主控台 AWS CLI、 或 AWS API 來建立自訂授權方資源。

在本教學課程中，您只需建立一個自訂授權方即可。本節說明如何使用 AWS IoT 主控台和 建立 AWS CLI，讓您可以使用最方便的方法。由任一種方法建立的自訂授權方資源之間沒有任何差異。

### 建立自訂授權方資源
<a name="custom-auth-tutorial-authorizer-resource"></a>

**選擇其中一個選項，來建立自訂授權方資源**
+ [使用 AWS IoT 主控台建立自訂授權方](#create-custom-auth-in-console)
+ [使用 AWS CLI建立自訂授權方](#create-custom-auth-in-cli)

**若要建立自訂授權方 (主控台)**

1. 開啟[AWS IoT 主控台的自訂授權方頁面](https://console.aws.amazon.com//iot/home#/authorizerhub)，然後選擇**建立授權方**。

1. 在**建立授權方**中：

   1. 在**授權方名稱**中，輸入 **my-new-authorizer**。

   1. 在**授權方狀態**中，勾選**作用中**。

   1. 在 **Authorizer function** (授權方函數) 中，選擇您先前建立的 Lambda 函數。

   1. 在 **Token validation - optional** (字符驗證 - 選用) 中：

      1. 切換**字符驗證**。

      1. 在**符記金鑰名稱**中，輸入 **tokenKeyName**。

      1. 選擇 **Add key (新增金鑰)**。

      1. 在**金鑰名稱**中，輸入 **FirstKey**。

      1. 在**公有金鑰**中，輸入 `public-key.pem` 檔案的內容。務必包括檔案中具有 `-----BEGIN PUBLIC KEY-----` 和 `-----END PUBLIC KEY-----` 的字行，並且不得從檔案內容中新增或刪除任何換行字元、歸位字元或其他字元。您輸入的字串應該看起來與這個範例相似。

         ```
         -----BEGIN PUBLIC KEY-----
         MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvEBzOk4vhN+3LgslvEWt
         sLCqNmt5Damas3bmiTRvq2gjRJ6KXGTGQChqArAJwL1a9dkS9+maaXC3vc6xzx9z
         QPu/vQOe5tyzz1MsKdmtFGxMqQ3qjEXAMPLEOmqyUKPP5mff58k6ePSfXAnzBH0q
         lg2HioefrpU5OSAnpuRAjYKofKjbc2Vrn6N2G7hV+IfTBvCElf0csalS/Rk4phD5
         oa4Y0GHISRnevypg5C8n9Rrz91PWGqP6M/q5DNJJXjMyleG92hQgu1N696bn5Dw8
         FhedszFa6b2x6xrItZFzewNQkPMLMFhNrQIIyvshtT/F1LVCS5+v8AQ8UGGDfZmv
         QeqAMAF7WgagDMXcfgKSVU8yid2sIm56qsCLMvD2Sq8Lgzpey9N5ON1o1Cvldwvc
         KrJJtgwW6hVqRGuShnownLpgG86M6neZ5sRMbVNZO8OzcobLngJ0Ibw9KkcUdklW
         gvZ6HEJqBY2XE70iEXAMPLETPHzhqvK6Ei1HGxpHsXx6BNft582J1VpgYjXha8oa
         /NN7l7Zbj/euAb41IVtmX8JrD9z613d1iM5L8HluJlUzn62Q+VeNV2tdA7MfPfMC
         8btGYladFAnitThaz6+F0VSBJPu7pZQoLnqyEp5zLMtF+kFl2yOBmGAP0RBivRd9
         JWBUCG0bqcLQPeQyjbXSOfUCAwEAAQ==
         -----END PUBLIC KEY-----
         ```

1. 選擇 **Create Authorizer** (建立授權方)。

1. 如果已建立自訂授權方資源，您會看到自訂授權方的清單，而且您的新自訂授權方應該會出現在清單中，接著您可以繼續進行下一節來測試它。

   如果您看到錯誤，請檢閱錯誤並嘗試重新建立您的自訂授權方，然後再次檢查這些項目。請注意，每個自訂授權方資源都必須具有唯一名稱。

**建立自訂授權方 (AWS CLI)**

1. 將您的值替代為 `authorizer-function-arn` 和 `token-signing-public-keys`，然後執行下列命令：

   ```
   aws iot create-authorizer \
   --authorizer-name "my-new-authorizer" \
   --token-key-name "tokenKeyName" \
   --status ACTIVE \
   --no-signing-disabled \
   --authorizer-function-arn "arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function" \
   --token-signing-public-keys FirstKey="-----BEGIN PUBLIC KEY-----
   MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvEBzOk4vhN+3LgslvEWt
   sLCqNmt5Damas3bmiTRvq2gjRJ6KXGTGQChqArAJwL1a9dkS9+maaXC3vc6xzx9z
   QPu/vQOe5tyzz1MsKdmtFGxMqQ3qjEXAMPLEOmqyUKPP5mff58k6ePSfXAnzBH0q
   lg2HioefrpU5OSAnpuRAjYKofKjbc2Vrn6N2G7hV+IfTBvCElf0csalS/Rk4phD5
   oa4Y0GHISRnevypg5C8n9Rrz91PWGqP6M/q5DNJJXjMyleG92hQgu1N696bn5Dw8
   FhedszFa6b2x6xrItZFzewNQkPMLMFhNrQIIyvshtT/F1LVCS5+v8AQ8UGGDfZmv
   QeqAMAF7WgagDMXcfgKSVU8yid2sIm56qsCLMvD2Sq8Lgzpey9N5ON1o1Cvldwvc
   KrJJtgwW6hVqRGuShnownLpgG86M6neZ5sRMbVNZO8OzcobLngJ0Ibw9KkcUdklW
   gvZ6HEJqBY2XE70iEXAMPLETPHzhqvK6Ei1HGxpHsXx6BNft582J1VpgYjXha8oa
   /NN7l7Zbj/euAb41IVtmX8JrD9z613d1iM5L8HluJlUzn62Q+VeNV2tdA7MfPfMC
   8btGYladFAnitThaz6+F0VSBJPu7pZQoLnqyEp5zLMtF+kFl2yOBmGAP0RBivRd9
   JWBUCG0bqcLQPeQyjbXSOfUCAwEAAQ==
   -----END PUBLIC KEY-----"
   ```

**其中：**
   + `authorizer-function-arn` 值是您為自訂授權方建立之 Lambda 函數的 Amazon 資源名稱 (ARN)。
   +  `token-signing-public-keys` 值包含金鑰的名稱 **FirstKey** 以及 `public-key.pem` 檔案的內容 務必包括檔案中具有 `-----BEGIN PUBLIC KEY-----` 和 `-----END PUBLIC KEY-----` 的字行，並且不得從檔案內容中新增或刪除任何換行字元、歸位字元或其他字元。

     注意：輸入公有金鑰時要小心，因為公有金鑰值若有任何更改，都會使其無法使用。

1. 如果已建立自訂授權方，則命令會傳回新資源的名稱和 ARN，如下所示。

   ```
   {
       "authorizerName": "my-new-authorizer",
       "authorizerArn": "arn:aws:iot:Region:57EXAMPLE833:authorizer/my-new-authorizer"
   }
   ```

   儲存 `authorizerArn` 值，以便用於下一個步驟。

   記住，每個自訂授權方資源都必須具有唯一名稱。

### 授權自訂授權方資源
<a name="custom-auth-tutorial-authorizer-permission"></a>

在本節中，您將許可您剛建立的自訂授權方資源執行 Lambda 函數。若要授與許可，您可以使用 [add-permission](https://docs.aws.amazon.com//cli/latest/reference/lambda/add-permission.html) CLI 命令。

**使用 將許可授予 Lambda 函數 AWS CLI**

1. 在插入您的值之後，輸入以下命令。請注意，`statement-id` 值必須是唯一的。如果您之前已執行本教學課程，或者如果您得到 `ResourceConflictException` 錯誤，請將 `Id-1234` 取代為另一個值，。

   ```
   aws lambda add-permission  \
   --function-name "custom-auth-function" \
   --principal "iot.amazonaws.com" \
   --action "lambda:InvokeFunction" \
   --statement-id "Id-1234" \
   --source-arn authorizerArn
   ```

1. 如果命令成功，它會傳回許可陳述式，例如此範例。您可以繼續下一節來測試自訂授權方。

   ```
   {
       "Statement": "{\"Sid\":\"Id-1234\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"iot.amazonaws.com\"},\"Action\":\"lambda:InvokeFunction\",\"Resource\":\"arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function\",\"Condition\":{\"ArnLike\":{\"AWS:SourceArn\":\"arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function\"}}}"
   }
   ```

   如果命令未成功，它會傳回錯誤，例如此範例。您必須先檢閱並更正錯誤，然後才能繼續進行。

   ```
   An error occurred (AccessDeniedException) when calling the AddPermission operation: User: arn:aws:iam::57EXAMPLE833:user/EXAMPLE-1 is not authorized to perform: lambda:AddPer
   mission on resource: arn:aws:lambda:Region:57EXAMPLE833:function:custom-auth-function
   ```

## 步驟 4：呼叫 test-invoke-authorizer 來測試授權方
<a name="custom-auth-tutorial-test"></a>

定義所有資源後，在本節中，您會從命令列呼叫 test-invoke-authorizer 來測試授權是否通過。

請注意，從命令列叫用授權方時，未定義 `protocolData`，因此授權方將一律傳回 DENY 文件。不過，此測試會確認您的自訂授權方和 Lambda 函數已正確設定，即使它未完全測試 Lambda 函數也一樣。

**使用 測試您的自訂授權方及其 Lambda 函數 AWS CLI**

1. 在具有您在前一個步驟中建立之 `private-key.pem` 檔案的目錄中，執行下列命令。

   ```
   echo -n "tokenKeyValue" | openssl dgst -sha256 -sign private-key.pem | openssl base64 -A
   ```

   此命令會建立要在下一個步驟中使用的簽章字串。簽章字串看起來像這樣：

   ```
   dBwykzlb+fo+JmSGdwoGr8dyC2qB/IyLefJJr+rbCvmu9Jl4KHAA9DG+V+MMWu09YSA86+64Y3Gt4tOykpZqn9mn
   VB1wyxp+0bDZh8hmqUAUH3fwi3fPjBvCa4cwNuLQNqBZzbCvsluv7i2IMjEg+CPY0zrWt1jr9BikgGPDxWkjaeeh
   bQHHTo357TegKs9pP30Uf4TrxypNmFswA5k7QIc01n4bIyRTm90OyZ94R4bdJsHNig1JePgnuOBvMGCEFE09jGjj
   szEHfgAUAQIWXiVGQj16BU1xKpTGSiTAwheLKUjITOEXAMPLECK3aHKYKY+d1vTvdthKtYHBq8MjhzJ0kggbt29V
   QJCb8RilN/P5+vcVniSXWPplyB5jkYs9UvG08REoy64AtizfUhvSul/r/F3VV8ITtQp3aXiUtcspACi6ca+tsDuX
   f3LzCwQQF/YSUy02u5XkWn+sto6KCkpNlkD0wU8gl3+kOzxrthnQ8gEajd5Iylx230iqcXo3osjPha7JDyWM5o+K
   EWckTe91I1mokDr5sJ4JXixvnJTVSx1li49IalW4en1DAkc1a0s2U2UNm236EXAMPLELotyh7h+flFeloZlAWQFH
   xRlXsPqiVKS1ZIUClaZWprh/orDJplpiWfBgBIOgokJIDGP9gwhXIIk7zWrGmWpMK9o=
   ```

   複製此簽章字串以在下一個步驟中使用。請小心不要包含任何額外的字元或留下任何額外的字元。

1. 在此命令中，會將 `token-signature` 值取代為來自前一個步驟的簽章字串，並執行此命令來測試您的授權方。

   ```
   aws iot test-invoke-authorizer \
   --authorizer-name my-new-authorizer \
   --token tokenKeyValue \
   --token-signature dBwykzlb+fo+JmSGdwoGr8dyC2qB/IyLefJJr+rbCvmu9Jl4KHAA9DG+V+MMWu09YSA86+64Y3Gt4tOykpZqn9mnVB1wyxp+0bDZh8hmqUAUH3fwi3fPjBvCa4cwNuLQNqBZzbCvsluv7i2IMjEg+CPY0zrWt1jr9BikgGPDxWkjaeehbQHHTo357TegKs9pP30Uf4TrxypNmFswA5k7QIc01n4bIyRTm90OyZ94R4bdJsHNig1JePgnuOBvMGCEFE09jGjjszEHfgAUAQIWXiVGQj16BU1xKpTGSiTAwheLKUjITOEXAMPLECK3aHKYKY+d1vTvdthKtYHBq8MjhzJ0kggbt29VQJCb8RilN/P5+vcVniSXWPplyB5jkYs9UvG08REoy64AtizfUhvSul/r/F3VV8ITtQp3aXiUtcspACi6ca+tsDuXf3LzCwQQF/YSUy02u5XkWn+sto6KCkpNlkD0wU8gl3+kOzxrthnQ8gEajd5Iylx230iqcXo3osjPha7JDyWM5o+KEWckTe91I1mokDr5sJ4JXixvnJTVSx1li49IalW4en1DAkc1a0s2U2UNm236EXAMPLELotyh7h+flFeloZlAWQFHxRlXsPqiVKS1ZIUClaZWprh/orDJplpiWfBgBIOgokJIDGP9gwhXIIk7zWrGmWpMK9o=
   ```

   如果命令成功，它會傳回自訂授權方函數產生的資訊，例如此範例。

   ```
   {
       "isAuthenticated": true,
       "principalId": "principalId",
       "policyDocuments": [
           "{\"Version\":\"2012-10-17\",		 	 	 \"Statement\":[{\"Action\":\"iot:*\",\"Effect\":\"Deny\",\"Resource\":\"arn:aws:iot:Region:57EXAMPLE833:*\"}]}"
       ],
       "refreshAfterInSeconds": 600,
       "disconnectAfterInSeconds": 3600
   }
   ```

   如果指令傳回錯誤，請檢閱錯誤並再次檢查您在本節中使用的命令。

## 步驟 5：使用 Postman 測試發佈 MQTT 郵件
<a name="custom-auth-tutorial-postman"></a>

1. 若要從命令列取得您的裝置資料端點，請呼叫 [describe-endpoint](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iot/describe-endpoint.html)，如這裡所示

   ```
   aws iot describe-endpoint --output text --endpoint-type iot:Data-ATS
   ```

   儲存此地址，以在稍後步驟中用作 *device\$1data\$1endpoint\$1address*。

1. 開啟新的 Postman 視窗並建立新的 HTTP POST 請求。

   1. 從您的電腦中，開啟 Postman 應用程式。

   1. 在 Postman 的 **File** (檔案) 選單中，選擇 **New** (新增)。

   1. 在 **New** (新增) 對話方塊中，選擇 **Request** (請求)。

   1. 在儲存請求中，

      1. 在 **Request name** (請求名稱) 中，輸入 **Custom authorizer test request**。

      1. 在 **Select a collection or folder to save to:** (選取要儲存到哪個集合或資料夾：) 中，選擇或建立要儲存此請求的集合。

      1. 選擇 ** Save to *collection\$1name*** (儲存至 collection\$1name)。

1. 建立 POST 請求來測試您的自訂授權方。

   1. 在 URL 欄位旁邊的請求方法選取器中，選擇 **POST**。

   1. 在 URL 欄位中，為您的請求建立 URL，方法為搭配使用下列 URL 與來自前一個步驟中 [describe-endpoint](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iot/describe-endpoint.html) 命令的 *device\$1data\$1endpoint\$1address*。

      ```
      https://device_data_endpoint_address:443/topics/test/cust-auth/topic?qos=0&actionToken=allow
      ```

      請注意，此 URL 包含 `actionToken=allow` 查詢參數，它會告訴您的 Lambda 函數傳回允許存取 AWS IoT的政策文件。輸入 URL 之後，查詢參數也會出現在 Postman 的 **Params** (參數) 標籤中。

   1. 在 **Auth** (身分驗證) 標籤的 **Type** (類型) 欄位中，選擇 **No Auth** (無需身分驗證)。

   1. 在標頭標籤中：

      1. 如果有已核取的 **Host** (主機) 金鑰，請取消核取此金鑰。

      1. 在標頭清單的底部，加入這些新標題並確認已核取它們。將 **Host** 值取代為您的 *device\$1data\$1endpoint\$1address*，並將 **x-amz-customauthorizer-signature** 值取代為在上節中與 **test-invoke-authorize** 命令搭配使用的簽章字串。    
[\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/zh_tw/iot/latest/developerguide/custom-auth-tutorial.html)

   1. 在主體標籤中：

      1. 在資料格式選項方塊中，選擇 **Raw** (原始)。

      1. 在資料類型清單中，選擇 **JavaScript**。

      1. 在文字欄位中，為您的測試訊息輸入此 JSON 訊息承載：

         ```
         {
             "data_mode": "test",
             "vibration": 200,
             "temperature": 40
         }
         ```

1. 選擇 **Send** (傳送) 以傳送請求。

   如果請求成功，它會傳回：

   ```
   {
       "message": "OK",
       "traceId": "ff35c33f-409a-ea90-b06f-fbEXAMPLE25c"
   }
   ```

   成功回應表示您的自訂授權方允許與 的連線， AWS IoT 且測試訊息已交付至 中的代理程式 AWS IoT Core。

   如果傳回錯誤，請檢閱錯誤訊息、*device\$1data\$1endpoint\$1address*、簽章字串，以及其他標頭值。

請將此請求保留在 Postman，以供下一節使用。

## 步驟 6：在 MQTT 測試用戶端中檢視訊息
<a name="custom-auth-tutorial-testclient"></a>

在上一個步驟中，您使用 Postman AWS IoT 將模擬裝置訊息傳送到 。成功回應指出您的自訂授權方允許連線到 AWS IoT ，並指出測試訊息已傳遞至 AWS IoT Core中的代理程式。在本節中，您將使用 AWS IoT 主控台中的 MQTT 測試用戶端，以其他裝置和服務可能的方式查看該訊息的訊息內容。

**若要查看自訂授權方所授權的測試訊息**

1. 在 AWS IoT 主控台中，開啟 [MQTT 測試用戶端](https://console.aws.amazon.com//iot/home#/test)。

1. 在 **Subscribe to topic** (訂閱主題) 標籤的 **Topic filter** (主題篩選條件) 中，輸入 **test/cust-auth/topic**，這是前一節的 Postman 範例中使用的訊息主題。

1. 選擇 **Subscribe (訂閱)**。

   保留此視窗讓後續步驟可以看到它。

1. 在 Postman 中，於您為前一節建立的請求中，選擇 **Send** (傳送)。

   檢閱回應以確定回應成功。如果未成功，請依照前一節所述疑難排解錯誤。

1. 在 **MQTT test client** (MQTT 測試用戶端) 中，您應該會看到顯示訊息主題的新項目，而且如果展開的話，則會看到您從 Postman 傳送之請求中的訊息承載。

   如果未在 **MQTT test client** (MQTT 測試用戶端) 中看到您的訊息，以下是一些需要檢查的事項：
   + 確定您的 Postman 請求成功傳回。如果 AWS IoT 拒絕連線並傳回錯誤，則請求中的訊息不會傳遞給訊息中介裝置。
   + 確定 AWS 區域 用來開啟 AWS IoT 主控台的 AWS 帳戶 和 與您在 Postman URL 中使用的 相同。
   + 請確定您使用自訂授權方的適當端點。預設 IoT 端點可能不支援搭配 Lambda 函數使用自訂授權方。反之，您可以使用網域組態來定義新的端點，然後為自訂授權方指定該端點。
   + 確定您已在 **MQTT test client** (MQTT 測試用戶端) 中正確地輸入主題。主題篩選條件會區分大小寫。如有疑問，您也可以訂閱 主題，該**\$1**主題會訂閱傳遞訊息代理程式 AWS 帳戶 並 AWS 區域 用來開啟 AWS IoT 主控台的所有 MQTT 訊息。

## 步驟 7：檢閱結果及後續步驟
<a name="custom-auth-tutorial-review"></a>

**在本教學課程中：**
+ 已將 Lambda 函數建立為自訂授權方處理常式
+ 已在啟用字符簽署的情況下建立自訂授權方
+ 已使用 **test-invoke-authorizer** 命令測試您的自訂授權方
+ 已使用 [Postman](https://www.postman.com/) 發佈 MQTT 主題，並利用您的自訂授權方驗證請求
+ 已使用 **MQTT test client** (MQTT 測試用戶端) 來檢視從 Postman 測試傳送的訊息

**後續步驟**  
從 Postman 傳送一些訊息以驗證自訂授權方是否正在運作之後，請試驗看看變更本教學課程的不同層面如何影響結果。以下是幾個入門範例。
+ 變更簽章字串，以便查看未經授權之連線嘗試的處理方式不再有效。您應該會得到錯誤回應 (例如這個錯誤回應)，且訊息應該不會出現在 **MQTT test client** (MQTT 測試用戶端) 中。

  ```
  {
      "message": "Forbidden",
      "traceId": "15969756-a4a4-917c-b47a-5433e25b1356"
  }
  ```
+ 若要進一步了解如何尋找在您開發和使用 AWS IoT 規則時可能發生的錯誤，請參閱 [監控 AWS IoT](monitoring_overview.md)。

## 步驟 8：清理
<a name="custom-auth-tutorial-cleanup"></a>

如果想要重複本教學課程，您可能需要移除某些自訂授權方。您的 AWS 帳戶 一次只能設定有限數量的自訂授權方，而且當您嘗試新增新的授權方而不移除現有的自訂授權方`LimitExceededException`時，您可以取得 。

**移除自訂授權方 (主控台)**

1. 開啟[AWS IoT 主控台的自訂授權方頁面](https://console.aws.amazon.com//iot/home#/authorizerhub)，然後在自訂授權方清單中，尋找要移除的自訂授權方。

1. 開啟自訂授權方詳細資訊頁面，然後從 **Actions** (動作) 選單中，選擇 **Edit** (編輯)。

1. 取消核取 **Activate authorizer** (啟用授權方)，然後選擇 **Update** (更新)。

   在自訂授權方作用中時，您無法將其刪除。

1. 從自訂授權方詳細資訊頁面中，開啟 **Actions** (動作) 選單，然後選擇 **Delete** (刪除)。

**移除自訂授權方 (AWS CLI)**

1. 列出您已安裝的自訂授權方，並找出要刪除的自訂授權方名稱。

   ```
   aws iot list-authorizers 
   ```

1. 在將 `Custom_Auth_Name` 取代為要刪除之自訂授權方的 `authorizerName` 之後，執行此命令將自訂授權方設定為 `inactive`。

   ```
   aws iot update-authorizer --status INACTIVE --authorizer-name Custom_Auth_Name
   ```

1. 在將 `Custom_Auth_Name` 取代為要刪除之自訂授權方的 `authorizerName` 之後，執行此命令來刪除自訂授權方。

   ```
   aws iot delete-authorizer --authorizer-name Custom_Auth_Name
   ```