2015-07-23 5 views
5

Ich arbeite an einem Oauth2-Tokensystem, um auf meine REST-API für meine Android-App zuzugreifen. Ich habe einige Probleme mit der Token-Erfrischung auf der Client-Seite. HierSo implementieren Sie einen Aktualisierungstokenprozess mit JWT für Android-Apps

ist der Fluss: Meine app eine Anfrage (mit einem Zugriffstoken in Parameter) auf den Server durch einige AsyncTask (PostCommentAsyncTask(), AddFriendAsyncTask() etc ...), also wenn die accessToken gültig ist, es ist in Ordnung, aber wenn es abgelaufen ist, rufe ich einen anderen AsyncTask (GetRefreshTokenAsyncTask()) von der onPostExecute() Methode des Präzedenzfalls AsyncTask, um neue accessToken zu erhalten. Hier ist der schwierige Teil für mich. Wenn ich das neue Zugriffs-Token bekomme, möchte ich die ursprüngliche AsyncTask-Anfrage an den Server erneut ausführen. Ich kann nicht herausfinden, wie es richtig gemacht wird.

example1:

Anfrage PostCommentAsyncTask() -> (acessToken abgelaufen) ->GetRefreshTokenAsyncTask() -> Anfrage PostCommentAsyncTask() -> (gut Token) -> Ok

EDIT:

Ich entschied mich schließlich für die Verwendung der Volley Bibliothek (keine Notwendigkeit, Asynctask mehr zu verwenden). Da ich JSON Web Token verwende, kann ich das Ablaufdatum überprüfen, das in der Nutzlast des Tokens kodiert ist. Hier

ist die isAccessTokenExpired() Methode zu überprüfen, ob das Zugriffstoken nicht, bevor sie eine Anfrage an den Server abgelaufen ist:

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

    } 

Und hier ist die refreshJsonWebToken() Methode ein neues Paar von Access Token/Refresh-Token zu erhalten von meinem OAuth2 Server:

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


    } 

Und finnally der getPost() Methode, wo ich die Präzedenzfall Methoden verwenden:

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

Sie konnten die 'bekommen verwenden()' Methode Ihrer zweiten 'AsyncTask' in 'doInBackground()' Methode der ersten 'AsyncTask'. Die Methode 'get()' von 'AsyncTask' ist eine Blocking-Methode, die ein Ergebnis zurückgibt - es ist völlig nutzlos, sie im main-/UI-Thread zu verwenden, aber wenn Sie sie vom ersten 'AsyncTask'-Befehl' doInBackground() 'aufrufen Methode (die auf einem eigenen Thread läuft), dann können Sie einfach mit der ursprünglichen Aufgabe fortfahren, sobald die zweite "AsyncTask" 'get()' Methode zurückkehrt. Nur eine Idee. – Squonk

+0

@ Frédéric: Welche Bibliothek haben Sie auf der Serverseite für die OAuth2 Passwortvergabe verwendet? Ich benutze Knoten als Backend. – j10

Antwort

0

Ich denke Handler ist in diesem Fall besser, weil Looper synchrone Nachrichtenwarteschlange hat, die hier bequem ist. Sie erstellen eine HandlerThread und verknüpfen Sie Ihre Handler damit. Dann können Sie postRunnable je nach Ihren Bedürfnissen anrufen, z. Sie fügen PostCommentRunnable hinzu, wenn Token abgelaufen ist, fügen Sie GetRefreshTokenRunnable und PostCommentRunnable hinzu, - sie werden sequentiell ausgeführt.

Wenn Sie immer noch mit AsyncTasks gehen möchten, können Sie überprüfen, ob das Token abgelaufen ist, bevor Sie PostCommentAsyncTask starten? Ich denke, das wird ein besseres Design sein. Wenn Sie nicht können, dann können Sie sie nacheinander ausgeführt werden, da sie standardmäßig auf dem gleichen Hintergrund-Thread arbeiten, zB:

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

Vielen Dank für Ihre Antwort! Ich kann das Token überprüfen, bevor ich tatsächlich eine Anfrage starte (Danke JWT).Ich bin neu in Android und ich weiß nicht viel über Handler, ich weiß nicht wirklich, wie Volley verarbeitet, aber es gibt ein Warteschlangensystem als Handler. Ich habe meinen Post mit etwas Arbeit editiert, hoffe, dass es verbessert werden könnte oder jemandem helfen könnte! –

+0

ok, vielen Dank für die Aktualisierung Ihres Posts. Also, was ist deine Frage jetzt? Ich denke, jetzt sollte alles klar sein –

Verwandte Themen