

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

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

 當 AWS IoT Core 叫用您的授權方時，它會觸發與授權方相關聯的 Lambda，其中包含下列 JSON 物件的事件。範例 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`：英數字串，作為自訂授權請求所傳送之字符的識別符。該值必須為英數字串 (字元數量不低於 1 個且不超過 128 個)，且符合此規則表達式 (regex) 模式：`([a-zA-Z0-9]){1,128}`。不允許非英數字元的特殊字元與 `principalId`搭配使用 AWS IoT Core。如果允許 使用非英數特殊字元，請參閱 AWS 其他服務的文件`principalId`。
+  `policyDocuments`：JSON 格式 AWS IoT Core 政策文件的清單 如需建立 AWS IoT Core 政策的詳細資訊，請參閱[AWS IoT Core 政策](iot-policies.md)。政策文件的數目上限為 10 份政策文件。每份政策文件最多可包含 2,048 個字元。
+  `disconnectAfterInSeconds`：整數，用來指定連接至 AWS IoT Core 閘道的持續時間上限 (以秒為單位)。最小值為 300 秒，最大值為 86,400 秒。預設值為 86，400。
**注意**  
建立連線時，會設定 的值 `disconnectAfterInSeconds`（由 Lambda 函數傳回）。在後續政策重新整理 Lambda 調用期間，無法修改此值。
+  `refreshAfterInSeconds`：整數，用來指定政策重新整理的間隔。一旦超出此間隔， AWS IoT Core 便會叫用 Lambda 函數，以允許政策重新整理。最小值為 300 秒，最大值為 86,400 秒。

  下列 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)。  在 MQTT over TLS 和 MQTT over WebSockets 連線中， 會在 `refreshAfterInSeconds` 欄位值中指定的間隔內 AWS IoT Core 快取此政策。如果採用 HTTP 連線，除非裝置使用的是 HTTP 持續連線 (也稱為 HTTP 保持連線或 HTTP 連線重複使用)，否則每個授權請求都會呼叫 Lambda 函數。您可以在設定授權方時選擇啟用快取。在此間隔期間， 會針對此快取政策 AWS IoT Core 授權已建立連線中的動作，而不會再次觸發您的 Lambda 函數。如果在自訂身分驗證期間發生失敗， 會 AWS IoT Core 終止連線。如果連線開啟的時間超過 `disconnectAfterInSeconds`參數中指定的值， AWS IoT Core 也會終止連線。

 下列 JavaScript 包含範例 Node.js Lambda 函數，其會在 MQTT Connect 訊息中尋找值為 的密碼，`test`並傳回政策，授予許可，以 AWS IoT Core 連接至名為 的用戶端，`myClientName`並發佈至包含相同用戶端名稱的主題。如果找不到預期的密碼，它會傳回拒絕這兩個動作的政策。

```
// 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 連結訊息的值。

```
{
  "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
}
```