在 Lambda 中获取用户的 IP 地址(使用 API 网关和 Python)
Get user's IP Address in Lambda (with API Gateway, and Python)
我使用的是这种技术 (),但它给出了 AWS 中 Lambda 服务器的 IP 地址。
基于此:,看来我应该可以使用
ip_address = event['requestContext']['identity']['sourceIp'];
我的处理程序是这样开始的:
def lambda_handler(event, context):
但是如果我执行 pprint.pprint(event)
,我在其中看不到任何 RequestContext,只有“正文”。
FFXSam 对 Jonathan 回答的最后评论说:“应该注意的是,如果您提供的页面不在授权方之后,则 event.requestContext.identity 不存在。”。
我不确定这意味着什么或为什么它是真的。我正在使用 API 网关,客户端的 JavaScript 代码正在调用它。
我可以要求客户端编码人员在正文中向我发送本地 IP 地址,但似乎我应该能够在 Lambda 函数本身中获取它。
有人要求事件,尽管我说它只有在名为“body”的 json 元素中传递的字段:
代码:
print("pprint event:")
pprint.pprint(event)
2021-06-06T13:30:01.231-05:00 pprint event:
2021-06-06T13:30:01.231-05:00 {'body': {'ResponseTimeMilliseconds': 2225,
2021-06-06T13:30:01.231-05:00 'authToken': '12312312',
2021-06-06T13:30:01.231-05:00 'handNumber': 7}}
你可以试试这个:
- 将 X-Forwarded-For 添加到“HTTP 请求 Headers”(转到 API-Gateway 配置 -> 资源 -> 方法请求)。
- 使用 Content-Type 添加模板:application/json(资源 -> 集成请求 -> “映射模板”)
- 向模板添加映射
{
"client_ip" : "$input.params('X-Forwarded-For')",
"user_agent" : "$input.params('User-Agent')"
}
- 现在 Headers 可以在 Lambda 中正常使用了:
event.client_ip
你也可以参考这个link:
https://forums.aws.amazon.com/thread.jspa?messageID=648053
我奖励了 Muzaffar Shaikh 的赏金,但在这里我将给出更详尽的解释,这似乎是 Whosebug 上缺少的。他的回答得到了 IP 地址,但删除了我的“正文”字段,但它确实为我指明了正确的方向。
在 AWS API 网关工具中,单击“资源”,然后单击您的方法(我的方法是“Post”),然后单击此处所示的“集成请求”。
向下滚动到底部,如果没有任何模板,请输入“application/json”并单击复选框(注意,“application/json”是浅灰色字母,但是只单击复选框而不输入是行不通的)。
然后我输入以下模板:
{
"client_ip" : "$input.params('X-Forwarded-For')",
"user_agent" : "$input.params('User-Agent')",
"body" : $input.json('$.body')
}
注意:如果我输入 $input.json('$') 或 $input.json('body'),我最终会在“正文”中得到一个“正文”字段字段,这打破了当前的逻辑。
网页完成后,看起来像这样:
下一步是将您的模板重新部署到您正在使用的“部署阶段”(环境)。
对了,在进入模板的时候,如果在“生成模板”下拉框中点击“方法请求透传”,会生成一个这样的模板(我没有用这个选项,但是会稍后阅读更多相关信息):
## See http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
## This template will pass through all parameters including path, querystring, header, stage variables, and context through to the integration endpoint via the body/payload
#set($allParams = $input.params())
{
"body-json" : $input.json('$'),
"params" : {
#foreach($type in $allParams.keySet())
#set($params = $allParams.get($type))
"$type" : {
#foreach($paramName in $params.keySet())
"$paramName" : "$util.escapeJavaScript($params.get($paramName))"
#if($foreach.hasNext),#end
#end
}
#if($foreach.hasNext),#end
#end
},
"stage-variables" : {
#foreach($key in $stageVariables.keySet())
"$key" : "$util.escapeJavaScript($stageVariables.get($key))"
#if($foreach.hasNext),#end
#end
},
"context" : {
"account-id" : "$context.identity.accountId",
"api-id" : "$context.apiId",
"api-key" : "$context.identity.apiKey",
"authorizer-principal-id" : "$context.authorizer.principalId",
"caller" : "$context.identity.caller",
"cognito-authentication-provider" : "$context.identity.cognitoAuthenticationProvider",
"cognito-authentication-type" : "$context.identity.cognitoAuthenticationType",
"cognito-identity-id" : "$context.identity.cognitoIdentityId",
"cognito-identity-pool-id" : "$context.identity.cognitoIdentityPoolId",
"http-method" : "$context.httpMethod",
"stage" : "$context.stage",
"source-ip" : "$context.identity.sourceIp",
"user" : "$context.identity.user",
"user-agent" : "$context.identity.userAgent",
"user-arn" : "$context.identity.userArn",
"request-id" : "$context.requestId",
"resource-id" : "$context.resourceId",
"resource-path" : "$context.resourcePath"
}
}
两个映射模板参考:
- https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
- https://docs.aws.amazon.com/apigateway/latest/developerguide/models-mappings.html
关于何时使用“$input.params”与“$context.some_value”,我还有一些研究要做。
我费了好大劲才找到如何在我的集成请求中添加映射模板。不确定发生了什么,但对于遇到此问题的任何人,我所做的是:
选中集成请求中的使用 Lambda 代理集成复选框。
现在我可以使用 event.["headers"]
.
在我的 Python lambda 函数中非常轻松地访问我的 header
添加屏幕截图以方便查找:
在您的 API 的相关方法中转到集成请求。 (看看我是如何按照其他答案的建议在方法请求中添加 X-Forwarded-For header 的)
复选框在这里:
(我没有制作映射模板。真的不知道这里发生了什么。)
我使用的是这种技术 (
基于此:
ip_address = event['requestContext']['identity']['sourceIp'];
我的处理程序是这样开始的:
def lambda_handler(event, context):
但是如果我执行 pprint.pprint(event)
,我在其中看不到任何 RequestContext,只有“正文”。
FFXSam 对 Jonathan 回答的最后评论说:“应该注意的是,如果您提供的页面不在授权方之后,则 event.requestContext.identity 不存在。”。 我不确定这意味着什么或为什么它是真的。我正在使用 API 网关,客户端的 JavaScript 代码正在调用它。
我可以要求客户端编码人员在正文中向我发送本地 IP 地址,但似乎我应该能够在 Lambda 函数本身中获取它。
有人要求事件,尽管我说它只有在名为“body”的 json 元素中传递的字段:
代码:
print("pprint event:")
pprint.pprint(event)
2021-06-06T13:30:01.231-05:00 pprint event:
2021-06-06T13:30:01.231-05:00 {'body': {'ResponseTimeMilliseconds': 2225,
2021-06-06T13:30:01.231-05:00 'authToken': '12312312',
2021-06-06T13:30:01.231-05:00 'handNumber': 7}}
你可以试试这个:
- 将 X-Forwarded-For 添加到“HTTP 请求 Headers”(转到 API-Gateway 配置 -> 资源 -> 方法请求)。
- 使用 Content-Type 添加模板:application/json(资源 -> 集成请求 -> “映射模板”)
- 向模板添加映射
{
"client_ip" : "$input.params('X-Forwarded-For')",
"user_agent" : "$input.params('User-Agent')"
}
- 现在 Headers 可以在 Lambda 中正常使用了:
event.client_ip
你也可以参考这个link: https://forums.aws.amazon.com/thread.jspa?messageID=648053
我奖励了 Muzaffar Shaikh 的赏金,但在这里我将给出更详尽的解释,这似乎是 Whosebug 上缺少的。他的回答得到了 IP 地址,但删除了我的“正文”字段,但它确实为我指明了正确的方向。
在 AWS API 网关工具中,单击“资源”,然后单击您的方法(我的方法是“Post”),然后单击此处所示的“集成请求”。
向下滚动到底部,如果没有任何模板,请输入“application/json”并单击复选框(注意,“application/json”是浅灰色字母,但是只单击复选框而不输入是行不通的)。
{
"client_ip" : "$input.params('X-Forwarded-For')",
"user_agent" : "$input.params('User-Agent')",
"body" : $input.json('$.body')
}
注意:如果我输入 $input.json('$') 或 $input.json('body'),我最终会在“正文”中得到一个“正文”字段字段,这打破了当前的逻辑。
网页完成后,看起来像这样:
下一步是将您的模板重新部署到您正在使用的“部署阶段”(环境)。
对了,在进入模板的时候,如果在“生成模板”下拉框中点击“方法请求透传”,会生成一个这样的模板(我没有用这个选项,但是会稍后阅读更多相关信息):
## See http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
## This template will pass through all parameters including path, querystring, header, stage variables, and context through to the integration endpoint via the body/payload
#set($allParams = $input.params())
{
"body-json" : $input.json('$'),
"params" : {
#foreach($type in $allParams.keySet())
#set($params = $allParams.get($type))
"$type" : {
#foreach($paramName in $params.keySet())
"$paramName" : "$util.escapeJavaScript($params.get($paramName))"
#if($foreach.hasNext),#end
#end
}
#if($foreach.hasNext),#end
#end
},
"stage-variables" : {
#foreach($key in $stageVariables.keySet())
"$key" : "$util.escapeJavaScript($stageVariables.get($key))"
#if($foreach.hasNext),#end
#end
},
"context" : {
"account-id" : "$context.identity.accountId",
"api-id" : "$context.apiId",
"api-key" : "$context.identity.apiKey",
"authorizer-principal-id" : "$context.authorizer.principalId",
"caller" : "$context.identity.caller",
"cognito-authentication-provider" : "$context.identity.cognitoAuthenticationProvider",
"cognito-authentication-type" : "$context.identity.cognitoAuthenticationType",
"cognito-identity-id" : "$context.identity.cognitoIdentityId",
"cognito-identity-pool-id" : "$context.identity.cognitoIdentityPoolId",
"http-method" : "$context.httpMethod",
"stage" : "$context.stage",
"source-ip" : "$context.identity.sourceIp",
"user" : "$context.identity.user",
"user-agent" : "$context.identity.userAgent",
"user-arn" : "$context.identity.userArn",
"request-id" : "$context.requestId",
"resource-id" : "$context.resourceId",
"resource-path" : "$context.resourcePath"
}
}
两个映射模板参考:
- https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
- https://docs.aws.amazon.com/apigateway/latest/developerguide/models-mappings.html
关于何时使用“$input.params”与“$context.some_value”,我还有一些研究要做。
我费了好大劲才找到如何在我的集成请求中添加映射模板。不确定发生了什么,但对于遇到此问题的任何人,我所做的是:
选中集成请求中的使用 Lambda 代理集成复选框。
现在我可以使用 event.["headers"]
.
添加屏幕截图以方便查找:
在您的 API 的相关方法中转到集成请求。 (看看我是如何按照其他答案的建议在方法请求中添加 X-Forwarded-For header 的)
复选框在这里:
(我没有制作映射模板。真的不知道这里发生了什么。)