在 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);
}
}
在作为 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)器,名为 AwsProxyRequestArgumentBinder
和 ContextArgumentBinder
。基于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/