本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。
HTTPAPIs透過 AWS Lambda 授權者控制存取
您可以使用 Lambda 授權器來使用 Lambda 函數來控制您的 HTTPAPI. 然後,當用戶端呼叫您的時候API,API閘道會叫用您的 Lambda 函數。API閘道會使用 Lambda 函數的回應來判斷用戶端是否可以存取您的API.
授權者承載資料格式版本可指定API閘道傳送給 Lambda 授權者的資料格式,以及API閘道如何解譯 Lambda 的回應。如果您未指定承載格式版本,預設 AWS Management Console 會使用最新版本。如果您使用 AWS CLI、 AWS CloudFormation或建立 Lambda 授權者SDK,則必須指定authorizerPayloadFormatVersion
. 支援的值為 1.0
和 2.0
。
如果您需要兼容性 RESTAPIs,請使用版本1.0
。
下列範例顯示每個裝載格式版本的結構。
- 2.0
-
{
"version": "2.0",
"type": "REQUEST",
"routeArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
"identitySource": ["user1", "123"],
"routeKey": "$default",
"rawPath": "/my/path",
"rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value",
"cookies": ["cookie1", "cookie2"],
"headers": {
"header1": "value1",
"header2": "value2"
},
"queryStringParameters": {
"parameter1": "value1,value2",
"parameter2": "value"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "api-id",
"authentication": {
"clientCert": {
"clientCertPem": "CERT_CONTENT",
"subjectDN": "www.example.com",
"issuerDN": "Example issuer",
"serialNumber": "1",
"validity": {
"notBefore": "May 28 12:30:02 2019 GMT",
"notAfter": "Aug 5 09:36:04 2021 GMT"
}
}
},
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"http": {
"method": "POST",
"path": "/my/path",
"protocol": "HTTP/1.1",
"sourceIp": "IP",
"userAgent": "agent"
},
"requestId": "id",
"routeKey": "$default",
"stage": "$default",
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
"pathParameters": { "parameter1": "value1" },
"stageVariables": { "stageVariable1": "value1", "stageVariable2": "value2" }
}
- 1.0
-
{
"version": "1.0",
"type": "REQUEST",
"methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
"identitySource": "user1,123",
"authorizationToken": "user1,123",
"resource": "/request",
"path": "/request",
"httpMethod": "GET",
"headers": {
"X-AMZ-Date": "20170718T062915Z",
"Accept": "*/*",
"HeaderAuth1": "headerValue1",
"CloudFront-Viewer-Country": "US",
"CloudFront-Forwarded-Proto": "https",
"CloudFront-Is-Tablet-Viewer": "false",
"CloudFront-Is-Mobile-Viewer": "false",
"User-Agent": "..."
},
"queryStringParameters": {
"QueryString1": "queryValue1"
},
"pathParameters": {},
"stageVariables": {
"StageVar1": "stageValue1"
},
"requestContext": {
"path": "/request",
"accountId": "123456789012",
"resourceId": "05c7jb",
"stage": "test",
"requestId": "...",
"identity": {
"apiKey": "...",
"sourceIp": "...",
"clientCert": {
"clientCertPem": "CERT_CONTENT",
"subjectDN": "www.example.com",
"issuerDN": "Example issuer",
"serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
"validity": {
"notBefore": "May 28 12:30:02 2019 GMT",
"notAfter": "Aug 5 09:36:04 2021 GMT"
}
}
},
"resourcePath": "/request",
"httpMethod": "GET",
"apiId": "abcdef123"
}
}
承載格式版本會決定 Lambda 函數必須傳回的回應結構。
格式 1.0 的 Lambda 函數回應
如果您選擇1.0
格式版本,Lambda 授權者必須傳回允許或拒絕存取您API路由的IAM政策。您可以在IAM策略中使用標準策略語法。如需 IAM 政策範例,請參閱控制調用的訪問 API。您可以使用 $context.authorizer.property
將內容屬性傳遞給 Lambda 整合或存取日誌。context
物件為選擇性,claims
是保留的預留位置,不能用作內容物件。如需進一步了解,請參閱自訂HTTPAPI存取記錄。
{
"principalId": "abcdef", // The principal user identification associated with the token sent by the client.
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow|Deny",
"Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
}
]
},
"context": {
"exampleKey": "exampleValue"
}
}
格式 2.0 的 Lambda 函數回應
如果您選擇2.0
格式版本,IAM則可以從 Lambda 函數傳回布林值或使用標準IAM原則語法的政策。要傳回一個布林值,請啟用授權方的簡易回應。下列範例會示範您必須編碼 Lambda 函數才能傳回的格式。該 context
物件是選用的物件。您可以使用 $context.authorizer.property
將內容屬性傳遞給 Lambda 整合或存取日誌。如需進一步了解,請參閱自訂HTTPAPI存取記錄。
- Simple response
-
{
"isAuthorized": true/false,
"context": {
"exampleKey": "exampleValue"
}
}
- IAM policy
-
{
"principalId": "abcdef", // The principal user identification associated with the token sent by the client.
"policyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Action": "execute-api:Invoke",
"Effect": "Allow|Deny",
"Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
}
]
},
"context": {
"exampleKey": "exampleValue"
}
}
範例 Lambda 授權方函數
下列範例 Node.js Lambda 函數會示範您需要從 Lambda 函數傳回的 2.0
承載格式版本的必要回應格式。
- Simple response - Node.js
-
export const handler = async(event) => {
let response = {
"isAuthorized": false,
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": true,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
};
if (event.headers.authorization === "secretToken") {
console.log("allowed");
response = {
"isAuthorized": true,
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": true,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
};
}
return response;
};
- Simple response - Python
import json
def lambda_handler(event, context):
response = {
"isAuthorized": False,
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": True,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
}
try:
if (event["headers"]["authorization"] == "secretToken"):
response = {
"isAuthorized": True,
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": True,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
}
print('allowed')
return response
else:
print('denied')
return response
except BaseException:
print('denied')
return response
- IAM policy - Node.js
-
export const handler = async(event) => {
if (event.headers.authorization == "secretToken") {
console.log("allowed");
return {
"principalId": "abcdef", // The principal user identification associated with the token sent by the client.
"policyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": event.routeArn
}]
},
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": true,
"arrayKey": ["value1", "value2"],
"mapKey": { "value1": "value2" }
}
};
}
else {
console.log("denied");
return {
"principalId": "abcdef", // The principal user identification associated with the token sent by the client.
"policyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Action": "execute-api:Invoke",
"Effect": "Deny",
"Resource": event.routeArn
}]
},
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": true,
"arrayKey": ["value1", "value2"],
"mapKey": { "value1": "value2" }
}
};
}
};
- IAM policy - Python
import json
def lambda_handler(event, context):
response = {
# The principal user identification associated with the token sent by
# the client.
"principalId": "abcdef",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Action": "execute-api:Invoke",
"Effect": "Deny",
"Resource": event["routeArn"]
}]
},
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": True,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
}
try:
if (event["headers"]["authorization"] == "secretToken"):
response = {
# The principal user identification associated with the token
# sent by the client.
"principalId": "abcdef",
"policyDocument": {
"Version": "2012-10-17",
"Statement": [{
"Action": "execute-api:Invoke",
"Effect": "Allow",
"Resource": event["routeArn"]
}]
},
"context": {
"stringKey": "value",
"numberKey": 1,
"booleanKey": True,
"arrayKey": ["value1", "value2"],
"mapKey": {"value1": "value2"}
}
}
print('allowed')
return response
else:
print('denied')
return response
except BaseException:
print('denied')
return response
身分識別來源
您可以選擇性地指定 Lambda 授權方的身分來源。身分來源會指定授權請求所需的資料位置。例如,您可以指定標頭或查詢字串值做為身分來源。如果您指定身分來源,用戶端必須將其包含在請求中。如果用戶端的要求不包含身分識別來源,APIGateway 不會叫用您的 Lambda 授權者,且用戶端會收到401
錯誤訊息。
下表說明 Lambda 授權者支援的身分識別來源。
類型 |
範例 |
備註 |
標頭值 |
$ 請求. 頭。name |
網域名稱需區分大小寫。 |
查詢字串值 |
$ 請求. 查詢字符串。name |
查詢字串名稱區分大小寫。 |
環境變數 |
$ 上下文。variableName |
支援的內容變數值。 |
階段變數 |
$stageVariables.variableName |
階段變數的值。 |
快取授權方回應
您可以 Lambda 過指定 authorizerResultTtlInSeconds. 啟用授權者的快取時,APIGateway 會使用授權者的身分識別來源作為快取金鑰。如果用戶端在已設定的身分識別來源中指定相同的參數TTL,APIGateway 會使用快取的授權程式結果,而不是叫用 Lambda 函數。
若要啟用快取,您的授權方必須至少有一個身分來源。
如果您為授權者啟用簡單回應,則授權者的回應會完全允許或拒絕符合快取身分識別來源值的所有API要求。如需更精細的權限,請停用簡單回應並傳回IAM原則。
根據預設,APIGateway 會針對使用授權者的所有路由使用快取API的授權者回應。若要快取每個路由的回應,請新增 $context.routeKey
至授權方的身分來源。
建立 Lambda 授權方
建立 Lambda 授權者時,您可以指定要使用的API閘道器的 Lambda 函數。您必須使用函數的資源政策或IAM角色授與API閘道權限,才能叫用 Lambda 函數。在此範例中,我們更新函數的資源政策,以便它授與API閘道呼叫 Lambda 函數的權限。
aws apigatewayv2 create-authorizer \
--api-id abcdef123
\
--authorizer-type REQUEST \
--identity-source '$request.header.Authorization
' \
--name lambda-authorizer \
--authorizer-uri 'arn:aws:apigateway:us-west-2
:lambda:path/2015-03-31/functions/arn:aws:lambda:us-west-2:123456789012:function:my-function
/invocations' \
--authorizer-payload-format-version '2.0
' \
--enable-simple-responses
下列命令授與API閘道權限來叫用您的 Lambda 函數。如果 API Gateway 沒有調用您的函數的權限,則客戶端會收到一個500 Internal
Server Error
.
aws lambda add-permission \
--function-name my-authorizer-function
\
--statement-id apigateway-invoke-permissions-abc123 \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:us-west-2:123456789012:api-id/
authorizers/authorizer-id
"
建立授權者並授與 API Gateway 呼叫授權者之後,請更新您的路由以使用授權者。
aws apigatewayv2 update-route \
--api-id abcdef123
\
--route-id acd123
\
--authorization-type CUSTOM \
--authorizer-id def123
Lambda 授權方疑難排解
如果API閘道無法呼叫 Lambda 授權者,或您的 Lambda 授權者傳回無效格式的回應,用戶端會收到. 500 Internal Server
Error
若要疑難排解錯誤,請為您的API階段啟用存取記錄。在 $context.authorizer.error
記錄格式中包含日誌變數。
如果日誌指出 API Gateway 沒有調用您的函數的權限,請更新函數的資源策略或提供IAM角色以授予 API Gateway 調用您的授權者的權限。
如果日誌指出您的 Lambda 函數傳回無效的回應,請確認 Lambda 函數傳回所需格式的回應。