如何在作为 AWS Lambda 代理一部分的 Micronaut API 实现中获取 "requestContext" 数据
How to obtain "requestContext" data in a Micronaut API implementation being part of a AWS Lambda Proxy
在 AWS Lambda 代理中(作为使用 Cognito 授权的 API 网关的集成)我想在处理请求时获取用户 ID。 Lambda 是使用 Micronaut 在 Java 中编写的。同一个 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);
}
}
当通过 API 调用 Lambda 并作为 Cognito 用户进行身份验证时,input
steam 看起来像这样(一些细节被省略/更改为示例值并且 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 然后在幕后做了很多我还不完全理解的事情;然而,最后我能够在控制器 class:
中使用 micronaut 的注释定义 API 端点
@Controller("/")
public class TestController {
@Get("/test")
public HttpResponse<String> test(HttpRequest<?> request) {
String userId = ?
}
}
此示例是 GET /test
的请求处理程序。
HttpRequest object 包含原始请求的所有内容,如 headers 和其他内容,但不包括 AWS 网关添加到此的信息,如身份验证的结果。
我现在如何访问它,特别是通过输入传递给 Lambda 的 requestContext?我在这里遗漏了一些拼图。
Micronaut 定义了两个类型绑定器,称为 AwsProxyRequestArgumentBinder
and ContextArgumentBinder
. Based on the documentation 类型绑定参数只能在方法参数中按类型请求。
所以你应该可以使用其中之一:
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();
}
}
如果这不起作用,也许只需从源代码中复制这两个活页夹的功能。
source.getAttribute(RequestReader.LAMBDA_CONTEXT_PROPERTY);
或:
((MicronautAwsProxyRequest<?>) source).getAwsProxyRequest();
在 AWS Lambda 代理中(作为使用 Cognito 授权的 API 网关的集成)我想在处理请求时获取用户 ID。 Lambda 是使用 Micronaut 在 Java 中编写的。同一个 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);
}
}
当通过 API 调用 Lambda 并作为 Cognito 用户进行身份验证时,input
steam 看起来像这样(一些细节被省略/更改为示例值并且 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 然后在幕后做了很多我还不完全理解的事情;然而,最后我能够在控制器 class:
中使用 micronaut 的注释定义 API 端点@Controller("/")
public class TestController {
@Get("/test")
public HttpResponse<String> test(HttpRequest<?> request) {
String userId = ?
}
}
此示例是 GET /test
的请求处理程序。
HttpRequest object 包含原始请求的所有内容,如 headers 和其他内容,但不包括 AWS 网关添加到此的信息,如身份验证的结果。
我现在如何访问它,特别是通过输入传递给 Lambda 的 requestContext?我在这里遗漏了一些拼图。
Micronaut 定义了两个类型绑定器,称为 AwsProxyRequestArgumentBinder
and ContextArgumentBinder
. Based on the documentation 类型绑定参数只能在方法参数中按类型请求。
所以你应该可以使用其中之一:
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();
}
}
如果这不起作用,也许只需从源代码中复制这两个活页夹的功能。
source.getAttribute(RequestReader.LAMBDA_CONTEXT_PROPERTY);
或:
((MicronautAwsProxyRequest<?>) source).getAwsProxyRequest();