Android,OkHttp,AWS4Signer,aws-api-gateway - "缺少身份验证令牌"

时间:2018-04-17 20:07:22

标签: android aws-api-gateway okhttp3

我正在尝试使用okhttp在android中为aws api网关签署一个http请求。我或多或少地使用了此stackoverflow问题stackoverflow question

中的代码

我使用CognitoCachingCredentialsProvider()来获取credentialsProvider对象。然后我使用getCredentials()来获取凭据。然后,我使用以下内容:credentials.getAWSAccessKeyId(),credentials.getAWSSecretKey()和credentials.getSessionToken()来获取必要的密钥和令牌。我在邮递员中使用它们并且能够成功执行api网关。

使用okhttp在android中请求失败,返回带有消息" Missing Authentication Token"的代码403。

这就是我准备请求的方法:我构建一个DefaultRequest对象,设置端点和httpmethod。然后,我使用AWS4Signer对请求进行签名,将凭证对象作为signer.sign(defaultRequest,credentials)参数传递。

我通过在defaultRequest上调用getHeaders()来获取标题的映射。我创建了两个列表,一个名为密钥,一个名称为值。然后我遍历地图,将密钥和相应的值加载到两个列表中。

然后我按照以下方式构建我的okhttp请求:

Request request = new Request.Builder()
                    .url(my ApiEndPoint)
                    .addHeader(key.get(0), value.get(0))
                    .addHeader(key.get(1), value.get(1))
                    .addHeader(key.get(2), value.get(2))
                    .addHeader(key.get(3), value.get(3))
                    .addHeader("Content-Type", "application/x-www-form-urlencoded")
                    .post(body)
                    .build();

我注意到以下内容:

在标题地图中,键 x-amz-security-token 有一个值....以 hKADF87VZ44w9IvZ1gU =

结尾

打印出okhttp请求, x-amz-security-token 键有一个值....以 hKADF87VZ44w9IvZ1gU \ u003d

结尾

=被替换为\ u003d,这可能是问题吗?如果是这样,如何防止这种情况?

否则,我们将非常感谢您解决此问题的任何帮助。

感谢

1 个答案:

答案 0 :(得分:1)

设法解决问题。似乎将标题分配给OkHttp请求是问题所在。所以这是我的代码:

我首先获得AWSSessionCredentials凭据。然后:

   AmazonWebServiceRequest amazonWebServiceRequest = new AmazonWebServiceRequest() {
    };

    String API_GATEWAY_SERVICE_NAME = "execute-api";

    com.amazonaws.Request requestAws = new DefaultRequest(amazonWebServiceRequest, API_GATEWAY_SERVICE_NAME);

您可以使用服务端点:

URI uri = URI.create("https://apigateway.eu-west-1.amazonaws.com");

或您的api url(根据Api Gateway控制台阶段选项(已部署的api)调用api的url):

String invokeUrl = "https://xxxx.execute-api.eu-west-1.amazonaws.com/yyy/zzzzz";

//      using the invoke url
    URI uri = URI.create(invokeUrl);
    requestAws.setEndpoint(uri);
    requestAws.setResourcePath(invokeUrl);
    requestAws.setHttpMethod(HttpMethodName.POST);

现在签署请求

AWS4Signer signer = new AWS4Signer();
    signer.setServiceName(API_GATEWAY_SERVICE_NAME);
    signer.setRegionName(Region.getRegion(Regions.EU_WEST_1).getName());
    signer.sign(requestAws, credentials);

获取标题

//        get map of headers
    Map<String, String> headers = requestAws.getHeaders();
//        create objects for the headers to add manually in OkHttp request builder
    String x_date = null;
    String x_token = null;
    String authorization = null;
//get and assign values
    for (Map.Entry<String, String> entry : headers.entrySet()) {
        if (entry.getKey().equals("x-amz-security-token")) {
            x_token = entry.getValue();
        }
        if (entry.getKey().equals("X-Amz-Date")) {
            x_date = entry.getValue();
        }
        if (entry.getKey().equals("Authorization")) {
            authorization = entry.getValue();
        }
    }

构建OkHttp请求:

Request request = new Request.Builder()
            .url(invokeUrl)
            .addHeader("Content-Type", "application/json")
            .addHeader("X-Amz-Date", x_date)
            .addHeader("x-amz-security-token", x_token)
            .addHeader("Authorization", authorization)
            .post(body)
            .build();

现在拨打你的OkHttp电话。

希望这对某人有帮助。