2017-05-17 106 views
0

這種情況是我有一個登錄活動,它向php-rest-api發送用戶名和密碼,如果響應正常,它將顯示一個新活動(這裏是一個測試活動)。使用改進的令牌認證

然後,在新的活動中,使用我從登錄過程獲得的令牌,我可以通過改進來查詢數據庫。

問題是我需要保存來自登錄嘗試的cookie,以便在我的下一個請求中使用它。
我使用改裝:2.2.0和 我讀 How to retrieve cookies in Retrofit?Retrofit keeps forgeting my cookies :(Android ,我檢查了所有可能的解決方案。

我的應用程序工作,沒有錯誤發生,但我的第一和第二個活動中的標題字段值是不同的。

這是我改造的客戶:

public class RetrofitClient { 

    private static String BASE_URL = "http://192.168.0.100/rest/main.php/"; 
    private static Retrofit retrofit = null; 

    public static Retrofit getRetroftInstance() { 
     if (retrofit == null) { 

      OkHttpClient cl = new OkHttpClient().newBuilder().addInterceptor(new AuthInterceptor()).build(); 

      retrofit = new Retrofit.Builder() 
        .baseUrl(BASE_URL) 
        .addConverterFactory(GsonConverterFactory.create()) 
        // .client(client) 
        .build(); 
     } 

     return retrofit; 
    }} 

這是authenticationinceptor:
public class AuthInterceptor implements Interceptor { @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); request = request.newBuilder() .addHeader("X-XSRF-TOKEN", ServiceSharedPrefs.getInstance().getToken()) .build(); Response response = chain.proceed(request); return response; } }

這是我的登錄過程:

private void loginProcedure(final String username, final String password) { 
    //Creat a user base on the user input 
    UserDB user = new UserDB(username, password); 
    //send data to the api and get response 
    Call<ApiDB> call = retrofitInterfaceObject.checkCredentials(user); 
    call.enqueue(new Callback<ApiDB>() { 
     @Override 
     public void onResponse(Call<ApiDB> call, Response<ApiDB> response) { 
      //Unauthorized handling 
      if (response.code() == 401) { 
       Toast.makeText(LoginActivity.this, "in 401", Toast.LENGTH_SHORT).show(); 
       ServiceDialog 
         .getInstance() 
         .CreateDialog(LoginActivity.this, 
           String.valueOf(response.code()) 
             + LoginActivity.this.getString(R.string.login_unauthorized_error_title) 
           , LoginActivity.this.getString(R.string.login_unauthorized_error_message) 
           , LoginActivity.this.getString(R.string.Generall_Ok_Text), null, null, null, false, false); 
      } 
      //Handling the 200 response : 2 possibility 
      else if (response.code() == 200) { 
       //if login ok 
       if (response.body().getLogin() != null) { 
        if (response.body().getLogin().contains("yes")) { 
         for(int i =0 ;i < response.headers().size();i++){ 
          Log.v("mmmm login header:"+i,response.headers().name(i)); 
         } 
         sharedPrefs.setToken(response.headers().get("X-XSRF-TOKEN")); 
         sharedPrefs.saveData(username, password); 
         LoginActivity.this.startActivity(new Intent(LoginActivity.this, test_check.class)); 
        } 

       } 
       //if login not ok 
       else if (response.body().getError().contains("Error in authentication!")) { 
        ServiceDialog 
          .getInstance() 
          .CreateDialog(LoginActivity.this, LoginActivity.this.getString(R.string.login_credentials_error_title) 
            , LoginActivity.this.getString(R.string.login_credentials_error_message) 
            , LoginActivity.this.getString(R.string.Generall_Ok_Text), null, null, null, false, false); 
       } 
      } 
      //Handle other situations 
      else { 
       ServiceDialog 
         .getInstance() 
         .CreateDialog(LoginActivity.this, response.code() + " : " + LoginActivity.this.getString(R.string.login_null_error_title) 
           , LoginActivity.this.getString(R.string.login_null_error_message) 
           , LoginActivity.this.getString(R.string.Generall_Ok_Text), null, null, null, false, false); 
      } 
     } 

     @Override 
     public void onFailure(Call<ApiDB> call, Throwable t) { 
      ServiceDialog.getInstance().CreateDialog(LoginActivity.this, LoginActivity.this.getString(R.string.login_null_error_title) 
        , t.getMessage() + "\n" + t.getLocalizedMessage(), LoginActivity.this.getString(R.string.Generall_Ok_Text), 
        null, null, null, true, true); 
     } 
    }); 

這是我的測試活動:

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_test_check); 
    final TextView t = (TextView) findViewById(R.id.txviewtest); 

    //t.setText(ping("192.168.0.100")); 


    Call<UserDB> call = this.ret.get1(ServiceSharedPrefs.getInstance().getToken()); 
    call.enqueue(new Callback<UserDB>() { 
     @Override 
     public void onResponse(Call<UserDB> call, Response<UserDB> response) { 
      for(int i =0 ;i < response.headers().size();i++){ 
       Log.v("mmmm check header:"+i,response.headers().name(i)); 
      } 
      t.append(ServiceSharedPrefs.getInstance().getToken()); 
      t.append("\n"); 
      t.append(String.valueOf(response.code())); 
      t.append("\n"); 
      t.append(response.headers().toString()); 
      t.append("\n"); 

      t.append(response.body().toString()); 

     } 
     @Override 
     public void onFailure(Call<UserDB> call, Throwable t) { 
      ServiceDialog.getInstance().CreateDialog(test_check.this, t.getMessage(), 
        null, getString(R.string.Generall_Ok_Text), null, null, null, true, true); 
     } 
    }); 

我的第一個標題:

login header:0: Date:Thu, 18 May 2017 08:10:50 GMT login header:1: Server:Apache/2.4.23 (Win64) PHP/5.6.25 login header:2: X-Powered-By:PHP/5.6.25 login header:3: Set-Cookie:XSRF-TOKEN=N18743296; path=/ login header:4: Expires:Thu, 19 Nov 1981 08:52:00 GMT login header:5: Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0 login header:6: Pragma:no-cache login header:7: Set-Cookie:XSRF-TOKEN=N18743296; path=/ login header:8: Set-Cookie:XSRF-TOKEN=N18743296; path=/ login header:9: X-XSRF-TOKEN:N18743296 login header:10: Content-Length:15 login header:11: Keep-Alive:timeout=5, max=100 login header:12: Connection:Keep-Alive login header:13: Content-Type:text/html; charset=UTF-8

我的第二個標題:

second header:0: Date:Thu, 18 May 2017 08:10:50 GMT second header:1: Server:Apache/2.4.23 (Win64) PHP/5.6.25 second header:2: X-Powered-By:PHP/5.6.25 second header:3: Set-Cookie:PHPSESSID=8ol17tht32l24fblejn2mjm9d4; path=/; HttpOnly second header:4: Expires:Thu, 19 Nov 1981 08:52:00 GMT second header:5: Cache-Control:no-store, no-cache, must-revalidate, post-check=0, pre-check=0 second header:6: Pragma:no-cache second header:7: Content-Length:154 second header:8: Keep-Alive:timeout=5, max=99 second header:9: Connection:Keep-Alive second header:10: Content-Type:application/json; charset=utf-8

+0

起飛看看客戶經理 – AndroidSmoker74

回答

0

你試過保存令牌SharedPreferences?我發現在這裏保存令牌更容易,並在準備好構建請求時訪問它。我使用intercepter,它工作得很好。

+0

我在我的共享首選項中有令牌。我的問題是,在第二個請求中,我可以從第一個請求中獲取cookie。我想我需要再次通過第一個請求中的所有頭文件,但通過使用攔截沒有任何反應。 – AEF

+0

檢查您保存令牌的位置。看起來,服務器在第一次請求後正在向您發送新令牌。也許確保你只設置一次? – Jlange

0

將您在第一個活動中獲得的令牌保存到Sharedpreferences中並使用它,如下所示。在兩個地方里面*代碼應該解決您的問題

*** 
public class AuthInterceptor implements Interceptor { 

    @Override 
    public Response intercept(Chain chain) 
      throws IOException { 
     Request request = chain.request(); 
     if(prefs!=null && prefs.hasToken()){//essentially checking if the prefs has a non null token 
     request = request.newBuilder() 
       .addHeader("Authenticator", prefs.getToken()) 
       .build(); 
     } 
     Response response = chain.proceed(request); 
     return response; 
    } 
} 
*** 

retrofit = new Retrofit.Builder() 
       .baseUrl(BASE_URL) 
       .addConverterFactory(GsonConverterFactory.create()) 
       *** 
       .addInterceptor(new AuthInterceptor()) 
       //this is nota valid function.first we should ccreate a 
       //OkHttp client and add this intercept to it. 
       *** 
       // .client(client) 
       .build(); 
+0

我以前用過這個,甚至檢查了我的請求。沒有添加到請求中。 '.addHeader(「Authenticator」,prefs.getToken())' 這裏出了問題,我想沒有任何錯誤。 – AEF

+0

我更新了我的帖子,根據你的建議。你可以看到我的第一個和第二個標題是不同的。 – AEF

0

您好試試這個片斷人會接收cookies,當你登錄,登錄之後,人會設置cookie,並有令牌

public class RetrofitClient { 

    private static String BASE_URL = "http://192.168.0.100/rest/main.php/"; 
    private static Retrofit retrofit = null; 

    public static Retrofit getRetroftInstance() { 
     if (retrofit == null) { 

      OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); 
      httpClient.addNetworkInterceptor(new SessionRequestInterceptor()); 
      httpClient.addNetworkInterceptor(new ReceivedCookiesInterceptor()); 

      retrofit = new Retrofit.Builder() 
        .baseUrl(BASE_URL) 
        .addConverterFactory(GsonConverterFactory.create()) 
        .client(httpClient.build()) 
        .build(); 
     } 

     return retrofit; 
    }} 

public class ReceivedCookiesInterceptor implements Interceptor { 

    @Override 
    public Response intercept(Chain chain) throws IOException { 
     Response originalResponse = chain.proceed(chain.request()); 

     if (!originalResponse.headers("Set-Cookie").isEmpty()) { 
      HashSet<String> cookies = new HashSet<>(); 
      for (String header : originalResponse.headers("Set-Cookie")) { 
       cookies.add(header); 
       if(header.startsWith("XSRF-TOKEN")) { 
        String newCookie[]=header.split(";"); 
        System.out.println("newCookie Length: "+newCookie.length); 
        for(String ss:newCookie) { 
         if(ss.startsWith("XSRF-TOKEN")) { 
          System.out.println("Cookies ss: " + ss); 
          sharedPrefs.setToken(ss); 
         } 
        } 
       } 
      } 
     } 
     return originalResponse; 
    } 
} 

public class SessionRequestInterceptor implements Interceptor { 

    @Override 
    public Response intercept(Chain chain) throws IOException { 
     Request original = chain.request(); 

     Request.Builder request = original.newBuilder(); 

     request.header("Cookie",ServiceSharedPrefs.getInstance().getToken())); 

     request.method(original.method(), original.body()); 

     return chain.proceed(request.build()); 
    } 

} 
+0

它確實有幫助,但它不是答案。我通過使用cookieManager解決了我的問題。順便說一句,謝謝 – AEF