如何通过Android上的retrofit2调用带有Cognito凭证的API网关?
我在我的android应用程序中使用retrofit2
进行任何http/rest调用。现在我需要调用一个由Amazon AWS API Gateway生成的api。如何通过Android上的retrofit2调用带有Cognito凭证的API网关?
的AWS文档say我应该生成客户端代码抛出API网关控制台和使用类ApiClientFactory
建立请求:
ApiClientFactory factory = new ApiClientFactory();
// Use CognitoCachingCredentialsProvider to provide AWS credentials
// for the ApiClientFactory
AWSCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
context, // activity context
"identityPoolId", // Cognito identity pool id
Regions.US_EAST_1 // region of Cognito identity pool
};
factory.credentialsProvider(credentialsProvider);
// Create an instance of your SDK (this should come from the generated code).
final MyApiClient client = factory.build(MyApiClient.class);
// Invoke a method (e.g., 'parentPath1Get(param1,body)') exposed by your SDK.
// Here the method's return type is OriginalModel.
OriginalModel output = client.parentPath1Get(param1,body);
// You also have access to your API's models.
OriginalModel myModel = new OriginalModel();
myModel.setStreetAddress(streetAddress);
myModel.setCity(city);
myModel.setState(state);
myModel.setStreetNumber(streetNumber);
myModel.setNested(nested);
myModel.setPoBox(poBox);
相反,我想定义的API就像我会retrofit
:与我写的接口,将其连接到RxJava,OkHttp等...
我的问题是:如何使用Cognito Identity Provider签署改造请求?
创建基于@ thanhbinh84答案的OkHttp拦截。试一试:https://github.com/Ghedeon/AwsInterceptor
标记为接受的答案,没有真正测试这个,因为我现在不再有这个需要了,我没有时间测试它。我会撤销我接受的答案,如果有人尝试,并发现它不工作/我会很感激人们确认它也工作! –
签名过程记录在这里:http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html
但你也许可以尝试重用一些从默认网关API客户端依赖于核心运行时组件的代码。由于签名过程是众所周知的,因此可能已有用于签署RxJava或OkHttp类型请求的库。
谢谢。我可能会在下个月需要这个。我希望有人会在此期间发布更多的细节,图书馆或其他内容。如果没有,我会自己从你给出的链接开始 –
我花了好几天才弄清楚如何使它工作。不知道他们为什么不指出课程而不是十几个文档页面。总共有4个步骤,你必须在工作线程,我使用Rxjava打电话,但你可以使用的AsyncTask代替:
Observable.create((Observable.OnSubscribe<String>) subscriber -> {
//Step 1: Get credential, ask server team for Identity pool id and regions
CognitoCachingCredentialsProvider credentialsProvider = new CognitoCachingCredentialsProvider(
this, // Context
"Identity Pool ID", // Identity Pool ID
Regions.US_EAST_1 // Region
);
//Step 2: Get these 3 three keys, test with postman v4.9.3 to see if identity is correct
String identityId = credentialsProvider.getIdentityId();
Log.show("identityId = " + identityId);
String AccessKey = credentialsProvider.getCredentials().getAWSAccessKeyId();
String SecretKey = credentialsProvider.getCredentials().getAWSSecretKey();
String SessionKey = credentialsProvider.getCredentials().getSessionToken();
Log.show("AccessKey = " + AccessKey);
Log.show("SecretKey = " + SecretKey);
Log.show("SessionKey = " + SessionKey);
//Step 3: Create an aws requets and sign by using AWS4Signer class
AmazonWebServiceRequest amazonWebServiceRequest = new AmazonWebServiceRequest() {
};
ClientConfiguration clientConfiguration = new ClientConfiguration();
String API_GATEWAY_SERVICE_NAME = "execute-api";
Request request = new DefaultRequest(amazonWebServiceRequest,API_GATEWAY_SERVICE_NAME);
request.setEndpoint(URI.create("YOUR_URI"));
request.setHttpMethod(HttpMethodName.GET);
AWS4Signer signer = new AWS4Signer();
signer.setServiceName(API_GATEWAY_SERVICE_NAME);
signer.setRegionName(Region.getRegion(Regions.US_EAST_1).getName());
signer.sign(request, credentialsProvider.getCredentials());
Log.show("Request header " + request.getHeaders().toString());
//Step 4: Create new request with authorization headers
OkHttpClient httpClient = new OkHttpClient();
Map<String, String> headers = request.getHeaders();
List<String> key = new ArrayList<String>();
List<String> value = new ArrayList<String>();
for (Map.Entry<String, String> entry : headers.entrySet())
{
key.add(entry.getKey());
value.add(entry.getValue());
}
try {
okhttp3.Request request2 = new okhttp3.Request.Builder()
.url("Your_url") // remember to add/to the end of the url, otherwise the signature will be different
.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")
.build();
Response response = null;
response = httpClient.newCall(request2).execute();
String body = response.body().string();
Log.show("response " + body);
} catch (Exception e) {
Log.show("error " + e);
}
subscriber.onNext(identityId);
}).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
Log.show("Throwable = " + e.getMessage());
}
@Override
public void onNext(String s) {
}
});
这里的关键是AWS4Signer类做4个步骤记录here,你不需要从头开始构建一个。为了使用AWS4Signer和AmazonWebServiceRequest,你需要导入AWS SDK的gradle中:
compile 'com.amazonaws:aws-android-sdk-cognito:2.3.9'
我现在没有机会测试这个,但除了需要一点清理似乎是正确的解决方案:)我会回来时,我可以, 谢谢。 (与此同时,我没有改造,但直接使用他们的SDK,因为我没有时间花在它上面) –
@DanieleSegato,我以后可能会切换到AWS SDK,那时我需要你的帮助。 :) – thanhbinh84
它更容易做,不干净,然后改装艰难(aka =更多样板):-) –
我最终直接使用了AWS SDK,并将其封装在Rx Observables中。 Jack Kohn的回答并没有错,但它也不是真正的答案,如果你想自己实施它,它只是指向正确的方向。 –
所以我试图挂钩与API网关的android,但如何或在哪里得到/创建类MyApiClient? – TheQ
这个名字取决于你的服务。 Theres是api网关的Web控制台的生成器/导出。尽管我没有使用这种方法。 –