Retrofit (1) — Basic Authentication on Android

这是Retrofit系列教程的第二章.本文将向你演示如何使用Retrofit来进行用户名和密码的基本认证.

在第一篇中,我们创建了第一个版本的能够执行API/HTTP请求的安卓客户端.现在我们将在它的基础上添加一些功能,使其能够完成基本的认证.

Integrate Basic Authentication 加入基本认证

现在我们为ServiceGenerator类创建一个添加了认证请求的方法.下面的代码就是拓展之后的ServiceGenerator类.有用于Retrofit1.9和Retrofit2的,看你自己需要的那个就好.

Retrofit1.9

public class ServiceGenerator {

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

    private static RestAdapter.Builder builder = new RestAdapter.Builder()
                .setEndpoint(API_BASE_URL)
                .setClient(new OkClient(new OkHttpClient()));

    public static <S> S createService(Class<S> serviceClass) {
        return createService(serviceClass, null, null);
    }

    public static <S> S createService(Class<S> serviceClass, String username, String password) {
        if (username != null && password != null) {
            // concatenate username and password with colon for authentication
            //认证的时候,用户名和密码用冒号连接
            String credentials = username + ":" + password;
            // create Base64 encodet string
            //用Base64对其加密
            final String basic =
                    "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);

            builder.setRequestInterceptor(new RequestInterceptor() {
                @Override
                public void intercept(RequestFacade request) {
                    request.addHeader("Authorization", basic);
                    request.addHeader("Accept", "application/json");
                }
            });
        }

        RestAdapter adapter = builder.build();
        return adapter.create(serviceClass);
    }
}

Retrofit2

public class ServiceGenerator {

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

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

    private static Retrofit.Builder builder =
            new Retrofit.Builder()
                    .baseUrl(API_BASE_URL)
                    .addConverterFactory(GsonConverterFactory.create());

    public static <S> S createService(Class<S> serviceClass) {
        return createService(serviceClass, null, null);
    }

    public static <S> S createService(Class<S> serviceClass, String username, String password) {
        if (username != null && password != null) {
            String credentials = username + ":" + password;
            final String basic =
                    "Basic " + Base64.encodeToString(credentials.getBytes(), Base64.NO_WRAP);

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

                    Request.Builder requestBuilder = original.newBuilder()
                        .header("Authorization", basic)
                        .header("Accept", "application/json")
                        .method(original.method(), original.body());

                    Request request = requestBuilder.build();
                    return chain.proceed(request);
                }
            });
        }
        OkHttpClient client = httpClient.build();
        Retrofit retrofit = builder.client(client).build();
        return retrofit.create(serviceClass);
    }
}

新的方法有两个新的参数:usernamepassword.你当然也可以用email来替代username.创建客户端的过程和第一个方法的是差不多的.对于任何HTTP请求和响应处理,我们都可以使用RestAdapter(Retrofit2中的是Retrofit)类来创建一个OkHttp客户端.

二者的不同在于,我们使用了拦截器RequestInterceptor(Retrofit2中的是Interceptor)来设置认证头部的值.但是这需要我们提供一个usernamepassword,没有的话,是不会执行的.如果你提供的用户名和密码没有通过认证,那么他将会创建一个和第一个方法一样的客户端.

在认证部分,我们还要调整给出的username/email和password的格式,需要把这两个值用冒号连接起来,然后把连接后的新字符串用Base64加密.

几乎所有的web服务器和API都会对HTTP请求的Authorization字段进行计算.所以我们要把一个加密的认证加入请求头部.假如你要访问的这个web服务器对用户的认证有其他的指定的头部字段,你就需要把认证调整到你的头部字段了.( In case the webservice you’re going to call with this client specifies another header field to expect the user’s credentials, adjust the header field from Authorization to your header field.)

如果你想接受到一个特殊格式的服务器响应,Accept头就显得很重要了.在这个例子里,我们想要接受的是JSON格式,因为Retrofit附带的GSON可以序列化返回的JSON内容.

Usage 使用

就像我们在上一篇文章里写的那个例子一样,在ServiceGenerator类里调用一个新方法就行了.我来演示给你看.

Retrofiit1.9

public interface LoginService {  
    @POST("/login")
    void basicLogin(Callback<User> cb);
}

Retrofit2

public interface LoginService {  
    @POST("/login")
    Call<User> basicLogin();
}

上面的接口只有一个方法:basicLogin.这个方法的返回值里有一个User来储存响应值,并且这个方法也没有添加任何查询参数和路径参数.

现在你可以创建一个HTTP客户端来发送你的认证了.

Retrofit1.9

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

    @Override
    public void failure(RetrofitError error) {
        // handle errors, too
    }
});

#### Retrofit2

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

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

ServiceGenerator方法将会创建一个包含了认证头部的HTTP客户端.只要你调用loginServicebasicLogin方法,提供的认证就会被自动得被发送.

翻译不当指出,请尽情指出,万分感谢.
原文:https://futurestud.io/tutorials/android-basic-authentication-with-retrofit