2. Retrofit2 -- Basic Authentication on Android

时间:2023-03-09 08:09:59
2. Retrofit2 -- Basic Authentication on Android

2. Retrofit2 -- Basic Authentication on Android

android
Retrofit
tutorial

上一节课中,我们创建了用于执行 API/HTTP 请求的原始 Android 客户端版本。本节课中,我们将使用上节课的客户端,对它进行增强,给它添加基本的认证功能。

整合基本的认证


首先,更新 ServiceGenerator 类,添加方法,用于把认证添加到请求上。下面的代码使用 1.92.0 版本分别进行了扩展:

Retrofit 1.9

  1. public class ServiceGenerator { 


  2. public static final String API_BASE_URL = "https://your.api-base.url"; 


  3. private static RestAdapter.Builder builder = new RestAdapter.Builder() 

  4. .setEndpoint(API_BASE_URL) 

  5. .setClient(new OkClient(new OkHttpClient())); 


  6. public static <S> S createService(Class<S> serviceClass) { 

  7. return createService(serviceClass, null, null); 




  8. public static <S> S createService(Class<S> serviceClass, String username, String password) { 

  9. if (username != null && password != null) { 

  10. // concatenate username and password with colon for authentication 

  11. String credentials = username + ":" + password; 

  12. // create Base64 encodet string 

  13. final String basic = 

  14. "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); 


  15. builder.setRequestInterceptor(new RequestInterceptor() { 

  16. @Override 

  17. public void intercept(RequestFacade request) { 

  18. request.addHeader("Authorization", basic); 

  19. request.addHeader("Accept", "application/json"); 



  20. }); 




  21. RestAdapter adapter = builder.build(); 

  22. return adapter.create(serviceClass); 





Retrofit 2.0

  1. public class ServiceGenerator { 


  2. public static final String API_BASE_URL = "https://your.api-base.url"; 


  3. private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder(); 


  4. private static Retrofit.Builder builder = 

  5. new Retrofit.Builder() 

  6. .baseUrl(API_BASE_URL) 

  7. .addConverterFactory(GsonConverterFactory.create()); 


  8. public static <S> S createService(Class<S> serviceClass) { 

  9. return createService(serviceClass, null, null); 




  10. public static <S> S createService(Class<S> serviceClass, String username, String password) { 

  11. if (username != null && password != null) { 

  12. String credentials = username + ":" + password; 

  13. final String basic = 

  14. "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP); 


  15. httpClient.addInterceptor(new Interceptor() { 

  16. @Override 

  17. public Response intercept(Interceptor.Chain chain) throws IOException { 

  18. Request original = chain.request(); 


  19. Request.Builder requestBuilder = original.newBuilder() 

  20. .header("Authorization", basic) 

  21. .header("Accept", "application/json") 

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


  23. Request request = requestBuilder.build(); 

  24. return chain.proceed(request); 



  25. }); 




  26. OkHttpClient client = httpClient.build(); 

  27. Retrofit retrofit = builder.client(client).build(); 

  28. 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. @Override 

  8. public void failure(RetrofitError error) { 

  9. // handle errors, too 



  10. }); 

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. @Override 

  12. public void onFailure(Call<User> call, Throwable t) { 

  13. // something went completely south (like no internet connection) 

  14. Log.d("Error", t.getMessage()); 





ServiceGenerator 方法将创建包含预定义认证头部的 HTTP 客户端。一旦调用 loginServicebasicLogin 方法,提供的认证信息将自动被传入到请求的 API 端点。