amazon-web-services - 如何在属于 AWS Lambda 代理的 Micronaut API 实现中获取 "requestContext"数据

标签 amazon-web-services aws-lambda aws-api-gateway micronaut micronaut-aws

在 AWS Lambda 代理(作为使用 Cognito 授权的 API 网关中的集成)中,我想在处理请求时获取用户 ID。 Lambda 是使用 Micronaut 用 Ja​​va 编写的。使用相同的 Lambda 作为多个 API 端点的集成。

我发现 Cognito 用户 ID 包含在提供给 Lambda 处理程序的代理数据的 requestContext 条目中:

public class Handler implements RequestStreamHandler {
    private static MicronautLambdaContainerHandler handler = new MicronautLambdaContainerHandler();

    @Override
    public void handleRequest(InputStream input, OutputStream output, Context context) throws IOException {
        // `input` contains the information I need (see below)
        handler.proxyStream(input, output, context);
    }
}

在作为 Cognito 用户进行身份验证时通过 API 调用 Lambda 时,输入 流如下所示(省略了一些详细信息/更改为示例值,并且 Cognito 用户 ID 标记为 //!!!):

{
    "resource": "/test",
    "path": "/test",
    "httpMethod": "GET",
    "headers": {
        "accept": "application/json, text/plain, */*",
        "accept-encoding": "gzip, deflate, br",
        "accept-language": "en-US,en;q=0.5",
        "Authorization": "Bearer eyJraWQiOiJPWlgzYVg3UWNITFwvM09vODg4SzhaYjBlcmRJMjZNNWFRdXF3a3VyZWhaVT0iLCJhbGciOiJSUzI1NiJ9[...]",
        "cache-control": "no-cache",
        "Host": "api.my-app.example.com",
        "origin": "https://my-app.example.com",
        "pragma": "no-cache",
        "referer": "https://my-app.example.com/home",
        "User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0",
        "X-Amzn-Trace-Id": "Root=1-5ebbd0f0-[...]",
        "X-Forwarded-For": "[...]",
        "X-Forwarded-Port": "443",
        "X-Forwarded-Proto": "https"
    },
    "multiValueHeaders": {
        /* similar to above but values being arrays */
    },
    "queryStringParameters": null,
    "multiValueQueryStringParameters": null,
    "pathParameters": {},
    "stageVariables": null,
    "requestContext": {
        "resourceId": "927cr8",
        "authorizer": {
            "claims": {
                "sub": "c99202cc-e088-43d6-8c15-1fd73a717a7c",    // !!!
                "cognito:groups": "[...]",
                "iss": "https://cognito-idp.eu-central-1.amazonaws.com/eu-central-1_[...]",
                "cognito:username": "c99202cc-e088-43d6-8c15-1fd73a717a7c",    // !!!
                "aud": "[...]",
                "event_id": "0d509360-d81e-4e7e-b346-9d018ed1cd04",
                "token_use": "id",
                "custom:[...]": "[...]",
                "auth_time": "1587536524",
                "name": "[...]",
                "exp": "Wed May 13 11:45:53 UTC 2020",
                "iat": "Wed May 13 10:45:53 UTC 2020",
                "email": "[...]"
            }
        },
        "resourcePath": "/test",
        "httpMethod": "GET",
        "extendedRequestId": "Md2VmF0OFiAFhZA=",
        "requestTime": "13/May/2020:10:50:24 +0000",
        "path": "/test",
        "accountId": "[...]",
        "protocol": "HTTP/1.1",
        "stage": "default",
        "domainPrefix": "api",
        "requestTimeEpoch": 1589367024516,
        "requestId": "feb2c8b2-4cf6-405b-bc48-76ebe33fde62",
        "identity": {
            "cognitoIdentityPoolId": null,
            "accountId": null,
            "cognitoIdentityId": null,
            "caller": null,
            "sourceIp": "[...]",
            "principalOrgId": null,
            "accessKey": null,
            "cognitoAuthenticationType": null,
            "cognitoAuthenticationProvider": null,
            "userArn": null,
            "userAgent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0",
            "user": null
        },
        "domainName": "api.my-app.example.com",
        "apiId": "[...]"
    },
    "body": null,
    "isBase64Encoded": false
}

MicronautLambdaContainerHandler 在幕后做了很多我还不完全理解的事情;然而,最终我能够在 Controller 类中使用 micronaut 的注释来定义 API 端点:

@Controller("/")
public class TestController {

    @Get("/test")
    public HttpResponse<String> test(HttpRequest<?> request) {
        String userId = ?
    }

}

此示例是 GET/test 的请求处理程序。

HttpRequest 对象包含原始请求中的所有内容,例如 header 和内容,但不包含 AWS 网关添加到其中的信息,例如身份验证结果。

我现在如何访问它,特别是通过其输入传递给 Lambda 的 requestContext?我在这里遗漏了一些拼图。

最佳答案

Micronaut 定义了两种类型的绑定(bind)器,名为 AwsProxyRequestArgumentBinderContextArgumentBinder 。基于documentation类型绑定(bind)参数只能在方法参数中按其类型请求。

所以你应该能够使用其中之一:

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.serverless.proxy.model.AwsProxyRequest;

@Controller("/")
public class TestController {

    @Get("/test")
    public HttpResponse<String> test(HttpRequest<?> request, Context context) {
        String userId = context.getAuthorizer().getClaims().getSubject();
    }

    @Get("/test")
    public HttpResponse<String> test2(HttpRequest<?> request, AwsProxyRequest awsRequest) {
        String userId = awsRequest.getRequestContext().getAuthorizer().getClaims().getSubject();
    }

}

如果这不起作用,也许只需从源代码中复制这两个 Binder 的功能即可。

source.getAttribute(RequestReader.LAMBDA_CONTEXT_PROPERTY);

或者:

((MicronautAwsProxyRequest<?>) source).getAwsProxyRequest();

关于amazon-web-services - 如何在属于 AWS Lambda 代理的 Micronaut API 实现中获取 "requestContext"数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61773686/

相关文章:

rest - 亚马逊 S3 : SDK or REST API

php - AWS PHP PDO MySQL 连接问题 SQLSTATE[HY000] [2002]

ruby-on-rails - Aws::S3::Errors::RequestTimeTooSkewed(请求时间与当前时间相差太大):

c# - 当 CORS OPTIONS 请求成功完成时,API 网关间歇性返回 "No ' Access-Control-Allow-Origin' header is present...”

amazon-web-services - AWS API 网关错误、与端点通信的网络错误、504 网关超时

python-3.x - AWS CDK API 网关 - 如何在不创建默认部署的情况下部署 API(python)

php - 来自 Amazon Linux 2 (Elastic Beanstalk) 的 Laravel artisan 修补匠

amazon-web-services - 如何使用 lambda Java SDK 从 SQS 读取所有消息,聚合所有这些消息并将它们作为单个 JSON 文件存储到 S3 存储桶?

amazon-web-services - 有没有办法使用 cloudformation 创建 aws lambda 执行角色?

amazon-web-services - 只允许 AWS API Gateway 访问 EC2 实例