在 Lambda 中获取用户的 IP 地址(使用 API 网关和 Python)

Nea*_*ers 3 amazon-web-services aws-lambda python-3.7

我正在使用这种技术(如何使用 Python 检索 AWS Lambda 公共 IP 地址?),但它提供了 AWS 内 Lambda 服务器的 IP 地址。

基于此:How can Iretrieve a user's public IP address via Amazon API Gateway + Lambda (node),看起来我应该能够使用

ip_address = event['requestContext']['identity']['sourceIp'];
Run Code Online (Sandbox Code Playgroud)

我的处理程序是这样开始的:

def lambda_handler(event, context):
Run Code Online (Sandbox Code Playgroud)

但如果我执行 a pprint.pprint(event),我在其中看不到任何 RequestContext,只有“正文”。

FFXSam 对 Jonathan 答案的最后评论说:“应该注意的是,如果您提供的页面不在授权者后面,则 event.requestContext.identity 不存在。”。我不确定这意味着什么或为什么这是真的。我正在使用 API Gateway,客户端的 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}}
Run Code Online (Sandbox Code Playgroud)

Nea*_*ers 11

我向 Muzaffar Shaikh 奖励了赏金,但在这里我将给出更彻底的解释,这在 StackOverflow 上似乎缺乏。他的回答得到了 IP 地址,但删除了我的“正文”字段,但这确实为我指明了正确的方向。

在 AWS API Gateway 工具中,单击“资源”,然后单击您的方法(我的是“发布”),然后单击“集成请求”,如下所示。 在此输入图像描述

向下滚动到底部,如果没有任何模板,请输入“application/json”并单击复选框(注意,“application/json”以浅灰色字母显示,但只需单击复选框而不输入它不会)工作)。

在此输入图像描述 然后我放入以下模板:

{
   "client_ip" : "$input.params('X-Forwarded-For')",
   "user_agent" : "$input.params('User-Agent')",
   "body" : $input.json('$.body') 
}
Run Code Online (Sandbox Code Playgroud)

注意:如果我放置 $input.json('$') 或 $input.json('body'),我最终会在“body”字段中得到一个“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"
    }
}
Run Code Online (Sandbox Code Playgroud)

映射模板的两个参考:

  1. https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
  2. https://docs.aws.amazon.com/apigateway/latest/developerguide/models-mappings.html

关于何时使用“$input.params”和“$context.some_value”,我还有一些研究要做。


Muz*_*ikh 5

你可以试试这个:

  1. 将 X-Forwarded-For 添加到“HTTP 请求标头”(转到 API 网关配置 -> 资源 -> 方法请求)。
  2. 添加内容类型为 application/json 的模板(资源 -> 集成请求 -> “映射模板”)
  3. 将映射添加到模板
{
   "client_ip" : "$input.params('X-Forwarded-For')",
   "user_agent" : "$input.params('User-Agent')"
}
Run Code Online (Sandbox Code Playgroud)
  1. 现在标头已按预期在 Lambda 中可用:

event.client_ip

您还可以参考此链接: https://forums.aws.amazon.com/thread.jspa ?messageID=648053