2016-08-03 22 views
5

Używam retrofit2 w moich aplikacjach na Androida dla każdego połączenia http/reszta. Teraz muszę zadzwonić do api generowane z Amazon AWS API Gateway.Jak wywołać API Gateway za pomocą Cognito Credentials przez retrofit2 na Androida?

Dokumentacja AWS say powinien wygenerować kod klienta rzucać konsolę bramy API i użyć klasy ApiClientFactory zbudować żądanie:

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); 

Zamiast tego chciałbym zdefiniować API jak bym z retrofit: z interfejsem, który piszę, podłącz go do RxJava, OkHttp itd ...

Moje pytanie brzmi: jak mogę podpisać prośby o modernizację za pomocą Cognito Identity Provider?

+0

Skończyłem z wykorzystaniem pakietu SDK AWS bezpośrednio i owijania go w Rx Observables na własną rękę. Odpowiedź Jacka Kohna nie jest zła, ale tak naprawdę nie jest również odpowiedzią, wskazuje tylko w dobrym kierunku, jeśli chcesz ją wdrożyć na własną rękę. –

+0

, więc próbuję podłączyć androida z bramą API, ale w jaki sposób lub gdzie otrzymałeś/stworzyłeś klasę 'MyApiClient'? – TheQ

+0

Nazwa zależy od Twoich usług. Jest generator/eksport z konsoli internetowej dla bramy APi. Nie skorzystałem z tej metody. –

Odpowiedz

1

Utworzono OkHttp przechwytywania oparciu @ thanhbinh84 odpowiedź. Wypróbuj: https://github.com/Ghedeon/AwsInterceptor

+0

Oznaczanie jako zaakceptowanej odpowiedzi bez testowania tego, ponieważ obecnie nie mam już tej potrzeby i nie mam czasu na testowanie to. Odbiorę zaakceptowaną odpowiedź, jeśli ktoś ją wypróbuje i okaże się, że nie działa. Byłbym wdzięczny, że osoby, które ją potwierdzają, również działają! –

1

Proces podpis jest udokumentowane tutaj: http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

Ale można prawdopodobnie spróbować ponownie użyć niektórych kodu z pakietu uruchomieniowego rdzeniowego, że domyślna brama API klienta zależy. Mogą istnieć już biblioteki do podpisywania żądań typu RxJava lub OkHttp, ponieważ proces podpisywania jest dobrze znany.

+0

dzięki. Będę potrzebował tego w przyszłym miesiącu. Mam nadzieję, że ktoś zamieści więcej szczegółów, bibliotekę lub coś w międzyczasie. Jeśli nie, sam to zrobię, poczynając od linku, który podałeś –

3

Zajęło mi kilka dni, aby dowiedzieć się, jak to działa. Nie wiem, dlaczego nie wskazują klasy zamiast tuzina stron dokumentu. Istnieje w sumie 4 kroki, należy zadzwonić w wątku roboczego, używam Rxjava ale można użyć AsyncTask zamiast:

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) { 

      } 
     }); 

Kluczem tutaj jest klasa AWS4Signer robi 4 kroki jako udokumentowane here, nie robić trzeba zbudować jeden od zera. W celu wykorzystania AWS4Signer i AmazonWebServiceRequest, trzeba importować AWS SDK w Gradle:

compile 'com.amazonaws:aws-android-sdk-cognito:2.3.9' 
+1

Nie mam teraz szansy na przetestowanie tego, ale oprócz potrzeby odrobiny porządków wydaje się to właściwym rozwiązaniem :) Wrócę do niego, kiedy będę mógł , dzięki. (w międzyczasie zrobiłem to bez modernizacji, ale używając SDK bezpośrednio, ponieważ nie miałem czasu na to wydać) –

+0

@ DanieleSegato, mogę przełączyć się na SDK AWS później, będę potrzebował twojej pomocy w tym czasie. :) – thanhbinh84

+0

Łatwiej jest to zrobić, mniej czysto niż później zmodernizować (aka = więcej opcji) :-) –