

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# 教程：为创建自定义授权方 AWS IoT Core
<a name="custom-auth-tutorial"></a>

本教程演示了使用 AWS CLI创建、验证和使用自定义身份验证的步骤。或者，使用本教程，您可以借助 HTTP Publish API 使用 Postman 将数据发送到 AWS IoT Core 。

本教程介绍如何创建一个示例 Lambda 函数，该函数将在启用令牌签名的情况下，借助 **create-authorizer** 调用实现授权和身份验证逻辑。然后使用对授权方进行验证，最后**test-invoke-authorizer**，您可以使用 HTTP 发布 API 向测试 MQTT 主题发送数据。 AWS IoT Core 示例请求将使用标头指定要调用的授权方，并在请求`x-amz-customauthorizer-name`标头`x-amz-customauthorizer-signature`中传递 token-key-name和。

**您将在本教程中学到的内容：**
+ 如何创建一个 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 安全最佳实践](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#) 控制台，打开[函数](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) 编辑器来编辑您的函数，只要源码不超过 3MB 即可。

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 API 创建自定义授权方 AWS CLI资源。

在本教程中，您只需要创建一个自定义授权方。本节介绍如何使用 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. 在**令牌验证 - 可选**中：

      1. 开启**令牌验证**。

      1. 在**令牌密钥名称**中，输入 **tokenKeyName**。

      1. 选择**添加密钥**。

      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. 选择 “**保存到” *collection\$1name***。

1. 创建 POST 请求以测试您的自定义授权方。

   1. 在 URL 字段旁边的请求方法选择器中，选择 **POST**。

   1. 在 URL 字段中，使用以下 URL 和上一步中的 desc [ribe-en *device\$1data\$1endpoint\$1address* dpoin](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/iot/describe-endpoint.html) t 命令来创建请求的网址。

      ```
      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_cn/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. 选择**订阅**。

   在下一步中，保持此窗口可见。

1. 在 Postman 中，在您为上一节创建的请求中，选择 **Send**（发送）。

   查看响应以确保响应成功。如果没有，请按照上一节所述对错误进行故障排除。

1. 在 **MQTT test client**（MQTT 测试客户端），您应该看到一个新条目，其中显示消息主题以及来自从 Postman 发送的请求（如果已展开）的消息有效载荷。

   如果您未在 **MQTT test client**（MQTT 测试客户端）中看到您的消息，可以检查以下事项：
   + 确保您的 Postman 请求成功返回。如果 AWS IoT 拒绝连接并返回错误，则请求中的消息不会传递给消息代理。
   + 确保 AWS 区域 用于打开 AWS IoT 控制台的 AWS 账户 和与你在 Postman URL 中使用的和相同。
   + 确保您为自定义授权方使用了适当的端点。默认的物联网端点可能不支持将自定义授权方与 Lambda 函数一起使用。相反，您可以使用域配置来定义新端点，然后为该自定义授权方指定该端点。
   + 请确保您已在 **MQTT test client**（MQTT 测试客户端）中正确输入主题。主题筛选条件区分大小写。如有疑问，您也可以订阅该**\$1**主题，该主题将订阅通过消息代理 AWS 账户 并 AWS 区域 用于打开控制台的所有 MQTT 消息。 AWS IoT 

## 步骤 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
   ```