如何用Java 11+ HttpClient调用AWS_IAM Auth Lambda Function URL

416 阅读1分钟

如果你的Lambda函数URL使用 AWS_IAMauth类型。


import software.amazon.awscdk.services.lambda.FunctionUrlAuthType;
import software.amazon.awscdk.services.lambda.FunctionUrlOptions;
    
var functionUrl = function.addFunctionUrl(FunctionUrlOptions.builder()
.authType(FunctionUrlAuthType.AWS_IAM)
    .build());

你必须使用AWS签名版本4(SigV4)签署每个HTTP请求。

Aws4Signer类与该依赖关系一起提供。


<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>auth</artifactId>
    <version>2.17.191</version>
</dependency>

...以及SDK。


<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>aws-sdk-java</artifactId>
    <version>2.17.191</version>
</dependency>

要签署一个请求。


import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse.BodyHandlers;
import java.util.List;

import org.junit.jupiter.api.Test;

import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider;
import software.amazon.awssdk.auth.signer.Aws4Signer;
import software.amazon.awssdk.auth.signer.params.Aws4SignerParams;
import software.amazon.awssdk.http.SdkHttpFullRequest;
import software.amazon.awssdk.http.SdkHttpMethod;
import software.amazon.awssdk.regions.Region;

public class JavaHTTP11ClientTest {

    @Test
    public void signedHttpGET() throws IOException, InterruptedException {
        var uri = URI.create("https://mtpe2t7ucalsample62y0zkfwq.lambda-url.eu-central-1.on.aws/hello/");
        var host = uri.getHost();
        var path = uri.getPath();

...你必须首先创建一个 SdkHttpFullRequest


        var fullRequest = SdkHttpFullRequest.builder()
                .encodedPath(path)
                .host(host)
                .protocol("https")
                .method(SdkHttpMethod.GET)
                .build();

请求被传递给AWS签名版本4(SigV4)工具,该工具执行签名。


        
        var signedRequest = Aws4Signer.create().sign(fullRequest,
            Aws4SignerParams.builder()
                    .signingName("lambda")
                    .awsCredentials(DefaultCredentialsProvider.create()
                                    .resolveCredentials())
                    .signingRegion(Region.EU_CENTRAL_1)
                    .build());

签名被作为AuthorizationX-Amz-Date 头信息传递给Java 11HttpClient


        //Java 11+ HttpClient          
        var client = HttpClient.newHttpClient();
        var builder = HttpRequest.newBuilder(uri);

        signedRequest.headers().forEach((name, list) -> addHeader(builder, name, list));
        var request = builder.GET().build();
        var response = client.send(request, BodyHandlers.ofString());
        var status = response.statusCode();
        var body = response.body();
        //...
    }

    static void addHeader(HttpRequest.Builder requestBuilder,String name, List<String> values){
        if(name.equalsIgnoreCase("host")){
            return;
        }
        values.forEach(value -> requestBuilder.header(name, value));
    }    
}

本例中的Lambda函数是基于Quarkus的MicroProfile,作为AWS Lambda函数,以Cloud Development Kit (CDK) v2 for Java模板部署