2. Retrofit2 -- Basic Authentication on Android


2. Retrofit2 -- Basic Authentication on Android

上一節課中,我們創建了用於執行 API/HTTP 請求的原始 Android 客戶端版本。本節課中,我們將使用上節課的客戶端,對它進行增強,給它添加基本的認證功能。

整合基本的認證


首先,更新 ServiceGenerator 類,添加方法,用於把認證添加到請求上。下面的代碼使用 1.92.0 版本分別進行了擴展:

Retrofit 1.9

  1. public class ServiceGenerator
  2.  
  3. public static final String API_BASE_URL = "https://your.api-base.url"
  4.  
  5. private static RestAdapter.Builder builder = new RestAdapter.Builder() 
  6. .setEndpoint(API_BASE_URL) 
  7. .setClient(new OkClient(new OkHttpClient())); 
  8.  
  9. public static <S> S createService(Class<S> serviceClass)
  10. return createService(serviceClass, null, null); 

  11.  
  12. public static <S> S createService(Class<S> serviceClass, String username, String password)
  13. if (username != null && password != null) { 
  14. // concatenate username and password with colon for authentication 
  15. String credentials = username + ":" + password; 
  16. // create Base64 encodet string 
  17. final String basic = 
  18. "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); 
  19.  
  20. builder.setRequestInterceptor(new RequestInterceptor() { 
  21. @Override 
  22. public void intercept(RequestFacade request)
  23. request.addHeader("Authorization", basic); 
  24. request.addHeader("Accept", "application/json"); 

  25. }); 

  26.  
  27. RestAdapter adapter = builder.build(); 
  28. return adapter.create(serviceClass); 


Retrofit 2.0

  1. public class ServiceGenerator
  2.  
  3. public static final String API_BASE_URL = "https://your.api-base.url"
  4.  
  5. private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); 
  6.  
  7. private static Retrofit.Builder builder = 
  8. new Retrofit.Builder() 
  9. .baseUrl(API_BASE_URL) 
  10. .addConverterFactory(GsonConverterFactory.create()); 
  11.  
  12. public static <S> S createService(Class<S> serviceClass)
  13. return createService(serviceClass, null, null); 

  14.  
  15. public static <S> S createService(Class<S> serviceClass, String username, String password)
  16. if (username != null && password != null) { 
  17. String credentials = username + ":" + password; 
  18. final String basic = 
  19. "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); 
  20.  
  21. httpClient.addInterceptor(new Interceptor() { 
  22. @Override 
  23. public Response intercept(Interceptor.Chain chain) throws IOException
  24. Request original = chain.request(); 
  25.  
  26. Request.Builder requestBuilder = original.newBuilder() 
  27. .header("Authorization", basic) 
  28. .header("Accept", "application/json"
  29. .method(original.method(), original.body()); 
  30.  
  31. Request request = requestBuilder.build(); 
  32. return chain.proceed(request); 

  33. }); 

  34.  
  35. OkHttpClient client = httpClient.build(); 
  36. Retrofit retrofit = builder.client(client).build(); 
  37. return retrofit.create(serviceClass); 


新方法中,多了兩個參數:usernamepassword。創建客戶端的基本方法與老方法一樣:使用 RestAdapter2.0 版本是 Retrofit)類為所有的 HTTP 請求和響應處理創建 OKHttp 客戶端。

新方法的不同在於:使用了 RequestInterceptor2.0 版本是 Inteceptor)類來為 OKHttp 客戶端執行的 HTTP 請求設置認證的頭部。當然,只有提供了 usernamepassword 參數,才會設置的。如果該方法沒有接收到 usernamepassword 參數,那么它創建的客戶端與第一個方法相同。

關於驗證部分,我們必須調整 usernamepassword 的格式。基本認證請求把所有值當作一個以逗號分隔的多行索引字符串。此外,新創建的字符串必須是 Base64 格式的編碼。

大多數的 webserviceAPI 都會對 HTTP 請求的認證頭部進行計算。這就是為什么我們要把編碼認證的值設置到頭部。如果你調用 web 服務的客戶端使用了其它的頭部字段來接收用戶的認證,那你應該把頭部的 Authorization 轉換為你服務所需的字段。

如果你想使用某種特定的格式來接收服務響應,那么,Accept 頭部字段起着決定性的作用。在示例中,我們要求服務器返回的信息格式是 JSON。這是因為我們配置了 retrofit 使用 Google GSON 把序列化的對象和 JSON 互相轉換。

用法


新方法的調用方法與上節課舊方法的調用方法一樣。假定,我們定義了一個 LoginService

Retrofit 1.9

  1. public interface LoginService {  
  2. @POST("/login"
  3. void basicLogin(Callback<User> cb)

Retrofit 2.0

  1. public interface LoginService {  
  2. @POST("/login"
  3. Call<User> basicLogin()

上面的接口只有一個方法:basicLogin。它的響應值類型是:User,沒有其它的查詢、或路徑參數。

現在,我們創建一個客戶端並把認證信息(username password)傳入:

Retrofit 1.9

  1. LoginService loginService =  
  2. ServiceGenerator.createService(LoginService.class, "user", "secretpassword"); 
  3. loginService.basicLogin(new Callback<User>() {  
  4. @Override 
  5. public void success(User user, Response response)
  6. // user object available 

  7.  
  8. @Override 
  9. public void failure(RetrofitError error)
  10. // handle errors, too 

  11. }); 

Retrofit 2.0

  1. LoginService loginService =  
  2. ServiceGenerator.createService(LoginService.class, "user", "secretpassword"); 
  3. Call<User> call = loginService.basicLogin();  
  4. call.enqueue(new Callback<User >() {  
  5. @Override 
  6. public void onResponse(Call<User> call, Response<User> response)
  7. if (response.isSuccessful()) { 
  8. // user object available 
  9. } else
  10. // error response, no access to resource? 


  11.  
  12. @Override 
  13. public void onFailure(Call<User> call, Throwable t)
  14. // something went completely south (like no internet connection) 
  15. Log.d("Error", t.getMessage()); 


ServiceGenerator 方法將創建包含預定義認證頭部的 HTTP 客戶端。一旦調用 loginServicebasicLogin 方法,提供的認證信息將自動被傳入到請求的 API 端點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM