2016-08-03 6 views
5

Ich verwende retrofit2 in meinen Android-Apps für jeden http/Rest Anruf. Jetzt muss ich eine mit Amazon AWS API Gateway generierte API aufrufen.So rufen Sie API Gateway mit Cognito-Anmeldeinformationen über Retrofit2 auf Android auf?

Die AWS Dokumentation say I der Client-Code in der API-Gateway-Konsole werfen und verwenden Sie die Klasse ApiClientFactory erzeugen sollte die Anforderung zu bauen:

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

Stattdessen würde Ich mag die API definieren, wie ich würde mit retrofit: mit einer Schnittstelle, die ich schreibe, verbinde es mit RxJava, OkHttp etc ...

Meine Frage ist: Wie kann ich die Nachrüstungsanträge mit Cognito Identity Provider signieren?

+0

Ich benutzte das AWS SDK direkt und verpackte es in Rx Observables auf eigene Faust. Die Antwort von Jack Kohn ist nicht falsch, aber es ist auch nicht wirklich eine Antwort, es zeigt nur in die richtige Richtung, wenn Sie es selbst implementieren wollen. –

+0

Ich versuche also, Android mit API-Gateway zu verbinden, aber wie oder wo hast du die Klasse 'MyApiClient' erstellt/erstellt? – TheQ

+0

Der Name hängt von Ihren Diensten ab. Theres ein Generator/Export von der Webkonsole für API-Gateway. Ich habe diese Methode jedoch nicht benutzt. –

Antwort

1

einen OkHttp Abfangjäger Erstellt basierend auf @ thanhbinh84 Antwort. Probieren Sie es aus: https://github.com/Ghedeon/AwsInterceptor

+0

Als akzeptierte Antwort markieren, ohne wirklich dies zu testen, weil ich derzeit diese Notwendigkeit nicht mehr habe und ich habe nicht die Zeit zu testen es. Ich werde meine akzeptierte Antwort widerrufen, wenn jemand es versucht und es nicht funktioniert/Ich würde es begrüßen, wenn Leute bestätigen, dass es auch funktioniert! –

1

Der Signaturprozess ist hier dokumentiert: http://docs.aws.amazon.com/general/latest/gr/signature-version-4.html

Aber Sie könnten wahrscheinlich versuchen, einige des Code aus dem Kern Runtime-Paket, das das Standard-API-Gateway-Client hängt davon ab, wieder zu verwenden. Es kann Bibliotheken geben, die bereits Anfragen vom Typ RxJava oder OkHttp signieren, da der Signaturprozess bekannt ist.

+0

danke. Ich werde das wahrscheinlich nächsten Monat brauchen. Ich hoffe, dass jemand in der Zwischenzeit weitere Details, eine Bibliothek oder etwas veröffentlichen wird. Wenn nicht, werde ich es selbst tun, ausgehend von dem Link, den du gegeben hast –

3

Ich brauchte mehrere Tage, um herauszufinden, wie es funktioniert. Ich weiß nicht, warum sie nicht auf die Klasse hinweisen, sondern auf Dutzende von Dokumentseiten. Es gibt 4 Stufen insgesamt, müssen Sie in Worker-Thread nennen, ich bin mit Rxjava aber Sie können AsyncTask statt:

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

      } 
     }); 

Der Schlüssel hier ist die AWS4Signer Klasse hat vier Schritte wie here dokumentiert, nicht wahr muss man von Grund auf neu bauen. Um AWS4Signer und AmazonWebServiceRequest zu verwenden, müssen Sie aws sdk in gradle importieren:

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

Ich habe keine Chance, das jetzt zu testen, aber abgesehen davon, dass ich ein bisschen Aufräumen brauche, scheint es die richtige Lösung zu sein :) Ich werde darauf zurückkommen, wenn ich kann , Vielen Dank. (In der Zwischenzeit habe ich ohne Nachrüstung, aber mit ihrem SDK direkt, weil ich keine Zeit hatte, um es zu verbringen) –

+0

@DanieleSegato, ich könnte später zu AWS SDK wechseln, ich brauche Ihre Hilfe, dass Zeit. :) – thanhbinh84

+0

Es ist einfacher zu tun, weniger sauber, dann nachrüsten tough (aka = mehr boilerplate) :-) –

Verwandte Themen