

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

# 定义您的 Lambda 函数
<a name="custom-auth-lambda"></a>

 当 AWS IoT Core 调用您的授权方时，它会使用包含以下 JSON 对象的事件触发与授权方关联的 Lambda。示例 JSON 对象包含所有可能的字段。不包括与连接请求无关的任何字段。

```
{
    "token" :"aToken",
    "signatureVerified": Boolean, // Indicates whether the device gateway has validated the signature.
    "protocols": ["tls", "http", "mqtt"], // Indicates which protocols to expect for the request.
    "protocolData": {
        "tls" : {
            "serverName": "serverName" // The server name indication (SNI) host_name string.
        },
        "http": {
            "headers": {
                "#{name}": "#{value}"
            },
            "queryString": "?#{name}=#{value}"
        },
        "mqtt": {
            "username": "myUserName",
            "password": "myPassword", // A base64-encoded string.
            "clientId": "myClientId" // Included in the event only when the device sends the value.
        }
    },
    "connectionMetadata": {
        "id": UUID // The connection ID. You can use this for logging.
    },
}
```

 Lambda 函数应使用此信息对传入连接进行身份验证，并决定允许在连接中执行哪些操作。函数应发送包含以下值的响应。
+  `isAuthenticated`：一个布尔值，指示是否已对请求进行身份验证。
+  `principalId`：字母数字字符串，它充当自定义授权请求发送的令牌的标识符。该值必须是包含至少一个字符且不超过 128 个字符的字母数字字符串，并与此正则表达式（正则表达式）模式匹配：`([a-zA-Z0-9]){1,128}`。不允许在 in `principalId` 中 AWS IoT Core使用非字母数字的特殊字符。如果允许使用非字母数字特殊字符，请参阅其他 AWS 服务的文档。`principalId`
+  `policyDocuments`：JSON 格式的 AWS IoT Core 策略文档列表有关创建 AWS IoT Core 策略的更多信息，请参阅。[AWS IoT Core 政策](iot-policies.md)策略文档的数量最多为 10 个。每个策略文档最多可以包含 2048 个字符。
+  `disconnectAfterInSeconds`：指定与 AWS IoT Core 网关的连接的最大持续时间（以秒为单位）的整数。最小值为 300 秒，最大值为 86400 秒。默认值是 86,400。
**注意**  
`disconnectAfterInSeconds` 的值（由 Lambda 函数返回）在建立连接时设置。在后续策略刷新 Lambda 调用过程中，将无法修改此值。
+  `refreshAfterInSeconds`：指定策略刷新之间间隔的整数。当此时间间隔过去时， AWS IoT Core 将调用 Lambda 函数以允许策略刷新。最小值为 300 秒，最大值为 86400 秒。

  以下 JSON 对象包含 Lambda 函数可以发送的响应示例。

 **\$1 "isAuthenticated":true, //A Boolean that determines whether client can connect. "principalId": "xxxxxxxx",  //A string that identifies the connection in logs. "disconnectAfterInSeconds": 86400,  "refreshAfterInSeconds": 300,   "policyDocuments": [       \$1         "Version": "2012-10-17",         "Statement": [            \$1               "Action": "iot:Publish",               "Effect": "Allow",               "Resource": "arn:aws:iot:us-east-1:<your\$1aws\$1account\$1id>:topic/customauthtesting"             \$1          ]        \$1     ] \$1**

 该`policyDocument`值必须包含有效的 AWS IoT Core 策略文档。有关 AWS IoT Core 策略的更多信息，请参阅[AWS IoT Core 政策](iot-policies.md)。 在 TLS 上的 MQTT 和通过 WebSockets连接的 MQ AWS IoT Core TT 中，在字段值中指定的间隔内缓存此策略。`refreshAfterInSeconds`在 HTTP 连接的情况下，每个授权请求都会调用 Lambda 函数，除非您的设备使用 HTTP 持久连接（也称为 HTTP 保持活动状态或 HTTP 连接重用），否则您可以在配置授权方时选择启用缓存。在此间隔内， AWS IoT Core 授权在已建立的连接中针对此缓存策略执行操作，而无需再次触发您的 Lambda 函数。如果在自定义身份验证期间出现故障，则 AWS IoT Core 终止连接。 AWS IoT Core 如果连接的打开时间超过`disconnectAfterInSeconds`参数中指定的值，也会终止该连接。

 以下内容 JavaScript 包含一个 Node.js Lambda 函数示例，该函数在 MQTT Connect 消息中查找值为`test`的密码，并返回一个策略，该策略授予使用`myClientName`名为的客户端进行连接 AWS IoT Core 并发布到包含相同客户端名称的主题的权限。如果未找到预期密码，则返回拒绝这两个操作的策略。

```
// A simple Lambda function for an authorizer. It demonstrates 
// how to parse an MQTT password and generate a response.

exports.handler = function(event, context, callback) { 
    var uname = event.protocolData.mqtt.username;
    var pwd = event.protocolData.mqtt.password;
    var buff = new Buffer(pwd, 'base64');
    var passwd = buff.toString('ascii');
    switch (passwd) { 
        case 'test': 
            callback(null, generateAuthResponse(passwd, 'Allow')); 
            break;
        default: 
            callback(null, generateAuthResponse(passwd, 'Deny'));  
    }
};

// Helper function to generate the authorization response.
var generateAuthResponse = function(token, effect) { 
    var authResponse = {}; 
    authResponse.isAuthenticated = true; 
    authResponse.principalId = 'TEST123'; 
    
    var policyDocument = {}; 
    policyDocument.Version = '2012-10-17';		 	 	 
    policyDocument.Statement = []; 
    var publishStatement = {}; 
    var connectStatement = {};
    connectStatement.Action = ["iot:Connect"];
    connectStatement.Effect = effect;
    connectStatement.Resource = ["arn:aws:iot:us-east-1:123456789012:client/myClientName"];
    publishStatement.Action = ["iot:Publish"]; 
    publishStatement.Effect = effect; 
    publishStatement.Resource = ["arn:aws:iot:us-east-1:123456789012:topic/telemetry/myClientName"]; 
    policyDocument.Statement[0] = connectStatement;
    policyDocument.Statement[1] = publishStatement; 
    authResponse.policyDocuments = [policyDocument]; 
    authResponse.disconnectAfterInSeconds = 3600; 
    authResponse.refreshAfterInSeconds = 300;
    
    return authResponse; 
}
```

 上述 Lambda 函数在收到 MQTT Connect 消息中的预期密码 `test` 时返回以下 JSON。`password` 和 `principalId` 属性的值将是来自 MQTT Connect 消息的值。

```
{
  "password": "password",
  "isAuthenticated": true,
  "principalId": "principalId",
  "policyDocuments": [
    {
      "Version": "2012-10-17",		 	 	 
      "Statement": [
        {
          "Action": "iot:Connect",
          "Effect": "Allow",
          "Resource": "*"
        },
        {
          "Action": "iot:Publish",
          "Effect": "Allow",
          "Resource": "arn:aws:iot:region:accountId:topic/telemetry/${iot:ClientId}"
        },
        {
          "Action": "iot:Subscribe",
          "Effect": "Allow",
          "Resource": "arn:aws:iot:region:accountId:topicfilter/telemetry/${iot:ClientId}"
        },
        {
          "Action": "iot:Receive",
          "Effect": "Allow",
          "Resource": "arn:aws:iot:region:accountId:topic/telemetry/${iot:ClientId}"
        }
      ]
    }
  ],
  "disconnectAfterInSeconds": 3600,
  "refreshAfterInSeconds": 300
}
```