2015-07-23 13 views
5

Pracuję nad systemem tokenów Oauth2, aby uzyskać dostęp do interfejsu API REST dla mojej aplikacji na Androida. Mam pewne problemy z częścią token refreshment po stronie klienta.Jak zaimplementować proces odświeżania tokena z JWT dla aplikacji na Androida

Oto przepływ: Moja aplikacja wysyła żądanie (z parametrem Token dostępu) do serwera dzięki asynktakowi (PostCommentAsyncTask(), AddFriendAsyncTask() itd.), Więc jeśli token dostępu jest ważny, to jest OK, ale jeśli jest stracił ważność Wywołuję inny AsyncTask (GetRefreshTokenAsyncTask()) z metodyz precedensu AsyncTask, aby uzyskać nowy accessToken. Tutaj jest dla mnie trudna część. Kiedy otrzymam nowy token dostępu, chcę ponownie wykonać pierwsze żądanie AsyncTask na serwerze. Nie mogę wymyślić, jak to zrobić właściwie.

example1:

prośba PostCommentAsyncTask() -> (acessToken wygasł) ->GetRefreshTokenAsyncTask() -> prośba PostCommentAsyncTask() -> (dobry znak) -> Ok

EDIT:

Ostatecznie zdecydowałem się użyć biblioteki Volley (nie trzeba już używać Asynctask). Jak używam JSON Web Token mogę sprawdzić datę ważności, która jest zakodowana w ładunku tokena.

Oto metoda isAccessTokenExpired() aby sprawdzić, czy dostęp Reklamowe nie upłynął przed złożeniem żądania do serwera:

public Boolean isAccessTokenExpired(String accessToken){ 

     String[] accessTokenPart = accessToken.split("\\."); 
     String header =accessTokenPart[0]; 
     String payload =accessTokenPart[1]; 
     String signature =accessTokenPart[2]; 

     try { 

      byte[] decodedPayload = Base64.decode(payload, Base64.DEFAULT); 
      payload = new String(decodedPayload,"UTF-8"); 
     } catch(UnsupportedEncodingException e) { 
      e.printStackTrace(); 
     } 


     try { 
      JSONObject obj = new JSONObject(payload); 
      int expireDate = obj.getInt("exp"); 
      Timestamp timestampExpireDate= new Timestamp(expireDate); 
      long time = System.currentTimeMillis(); 
      Timestamp timestamp = new Timestamp(time); 

      return timestamp.after(timestampExpireDate); 

     } catch (JSONException e) { 
      e.printStackTrace(); 
      return true; 
     } 

    } 

A oto metoda refreshJsonWebToken() dostać nową parę token dostępu/Refresh tokena z mojego serwera OAuth2:

public void refreshJsonWebToken(){ 


      SharedPreferences settings = getActivity().getSharedPreferences(PREFS_NAME, 0); 
      String refreshToken = settings.getString("refreshToken", null); 

      final HashMap<String, String> params = new HashMap<String, String>(); 
      params.put("grant_type","refresh_token"); 
      params.put("client_id","client"); 
      params.put("refresh_token",refreshToken); 

      JsonObjectRequest req = new JsonObjectRequest(URL_OAUTH2, new JSONObject(params), new Response.Listener<JSONObject>() { 

       @Override 
       public void onResponse(JSONObject response) { 

         try { 

          String newRefreshToken = response.getString("refresh_token"); 
          SharedPreferences settings = getActivity().getSharedPreferences(PREFS_NAME, 0); 
          SharedPreferences.Editor editor = settings.edit(); 
          editor.putString("accessToken", newAccessToken); 
          editor.putString("refreshToken", newRefreshToken); 
          editor.apply(); 
         } catch (JSONException e) { 
          e.printStackTrace(); 
         } 
        } 
      }, new Response.ErrorListener() { 


       @Override 
       public void onErrorResponse(VolleyError error) { 
        Log.e("grid", "Error: " + error.getMessage()); 

        } 
       } 
      }); 

      AppController.getInstance().addToRequestQueue(req); 


    } 

I Wreszcie dążyć metody getPost() gdzie używam metody zawieszających:

private void getPost(String latitude, String longitude) { 

     SharedPreferences settings = getActivity().getSharedPreferences(PREFS_NAME, 0); 
     String accessToken = settings.getString("accessToken", null); 
     final HashMap<String, String> params = new HashMap<String, String>(); 
     params.put("action", "getLocalPosts"); 
     params.put("latitude", latitude); 
     params.put("longitude", longitude); 

     if (isAccessTokenExpired(accessToken)){ 
      refreshJsonWebToken(); 
     } 

     settings = getActivity().getSharedPreferences(PREFS_NAME, 0); 
     accessToken = settings.getString("accessToken", null); 
     JsonObjectRequest req = new JsonObjectRequest(URL_APP+accessToken, new JSONObject(params), new Response.Listener<JSONObject>() { 

      //Some code .... 
     }); 

     AppController.getInstance().addToRequestQueue(req); 

    } 
+0

Możesz użyć metody 'get()' swojego drugiego 'AsyncTask' w 'doInBackground()' metoda twojego pierwszego 'AsyncTask'. Metoda 'get()' z 'AsyncTask' jest metodą blokującą, która zwraca wynik - użycie jej w wątku głównym/UI jest całkowicie bezużyteczne, ale jeśli wywołasz ją z pierwszego' DoInBackground() 'AsyncTask'() (która działa na własnym wątku), możesz po prostu kontynuować oryginalną czynność po zwróceniu drugiej metody 'get()' AsyncTask. Tylko pomysł. – Squonk

+0

@ Frédéric: Jaką bibliotekę używałeś po stronie serwera do udzielania haseł OAuth2? Używam węzła jako zaplecza. – j10

Odpowiedz

0

Myślę, że Handler jest lepszy w tym przypadku, ponieważ Looper ma synchroniczną kolejkę wiadomości, która jest wygodna tutaj. Tworzysz HandlerThread i powiążesz z nim swój Handler. Następnie możesz zadzwonić pod numer postRunnable w zależności od potrzeb, np. dodajesz PostCommentRunnable, jeśli token wygasł, dodajesz GetRefreshTokenRunnable i PostCommentRunnable, - będą wykonywane sekwencyjnie.

Jeśli nadal chcesz korzystać z AsyncTasks, czy możesz sprawdzić, czy token wygasł przed uruchomieniem PostCommentAsyncTask? Myślę, że będzie to lepszy projekt. Jeśli nie możesz, możesz wykonywać je jeden po drugim, ponieważ domyślnie działają na tym samym wątku tła, na przykład:

new PostCommentAsyncTask().execute(); 

class PostCommentAsyncTask extends AsyncTask { 
    //... 
    onPostExecute() { 
     if (tokenExpired) { 
      new GetRefreshTokenAsyncTask().execute(); 
      new PostCommentAsyncTask().execute(); // this guy will wait till refresh token is executed. 
     } 
    } 
} 
+1

Dziękuję za odpowiedź! Mogę sprawdzić token przed uruchomieniem żądania (dzięki JWT).Jestem nowy dla Androida i nie wiem zbyt wiele na temat Handlera, tak naprawdę nie wiem jak przebiega proces Volley, ale istnieje system kolejki jako Handler. Wydałem swój post z nadzieją, że uda się go ulepszyć lub pomóc każdemu! –

+0

ok, dziękuję za aktualizację swojego wpisu. więc, jakie jest twoje pytanie teraz? Myślę, że teraz wszystko powinno być jasne –

Powiązane problemy