使用Retrofit拦截器发送cookie以用于后续API调用

时间:2016-10-27 06:07:57

标签: android cookies retrofit retrofit2

我只是记录用户,在首选项中存储一些关键身份验证响应数据,并尝试在需要cookie的情况下执行后续HTTP GET调用。以下设置产生401未经授权的响应,这使我相信我正在不正确地处理Retrofit(v2.1.0)拦截器中的cookie。如何使用Retrofit拦截器发送cookie,然后允许我进行后续API调用?

示例摘自:https://gist.github.com/nikhiljha/52d45ca69a8415c6990d2a63f61184ff

认证

                OkHttpClient client = new OkHttpClient();
                OkHttpClient.Builder builder = new OkHttpClient.Builder();

                builder.addInterceptor(new AddCookiesInterceptor(context)); // VERY VERY IMPORTANT
                builder.addInterceptor(new ReceivedCookiesInterceptor(context)); // VERY VERY IMPORTANT
                client = builder.build();

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

                final MembershipApi service = retrofit.create(MembershipApi.class);

                UserCredentials userCredentials = new UserCredentials();
                userCredentials.setUsername(mUsername);
                userCredentials.setPassword(mPassword);
                userCredentials.setIncludeExchangeToken(true);
                userCredentials.setUserType("Member");
                userCredentials.setIncludeMemberConfig(true);

                Call<UserData> userDataCall = service.authenticateUsername(userCredentials);

                userDataCall.enqueue(new Callback<UserData>() {
                    @Override
                    public void onResponse(Call<UserData> call, Response<UserData> response) {
                        int statusCode = response.code();
                        String message = response.message();
                        UserData userData = response.body();
                        pbProgress.setVisibility(View.GONE);
                        Timber.v("onResponse " + statusCode);
                        Timber.v("onResponse " + message);
                        if (statusCode == 200) {
                            // Create user login session
                            Timber.v("login successful");

                            try {
                               // session is simply a helper class that stores key authentication response data in preferences
                               session.createUserLoginSession(
                                       userData.getMemberID(),
                                       userData.getClientID(),
                                       userData.getFullName(),
                                       userData.getMemberConfig().getClientNameMobile(),
                                       userData.getExchangeToken());

                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                            // launch feed activity
                            goFeed();

                        } else {
                            Timber.v("login failure");
                            Toast.makeText(getApplicationContext(), getResources().getString(R.string.text_login_failed), Toast.LENGTH_SHORT).show();
                        }
                    }

                    @Override
                    public void onFailure(Call<UserData> call, Throwable t) {
                        pbProgress.setVisibility(View.GONE);
                        Timber.v("onFailure: " + t.getMessage());
                    }
                });

后续GET检索Feed:

        OkHttpClient client = new OkHttpClient();
      OkHttpClient.Builder builder = new OkHttpClient.Builder();

        builder.addInterceptor(new AddCookiesInterceptor(this)); // VERY VERY IMPORTANT
        builder.addInterceptor(new ReceivedCookiesInterceptor(this)); // VERY VERY IMPORTANT
        client = builder.build();


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

        MembershipApi service = retrofit.create(MembershipApi.class);

        Call<FeedData> userDataCall = service.getFeed(Integer.parseInt(session.getClientId()), Integer.parseInt(session.getKeyMemberId()),
                                                        "All", 10, 1, 0, 0, "Android" );

        userDataCall.enqueue(new Callback<FeedData>() {
            @Override
            public void onResponse(Call<FeedData> call, Response<FeedData> response) {
                int statusCode = response.code();
                String message = response.message();
                Timber.v("onResponse " + statusCode);
                Timber.v("onResponse " + message);
                if (statusCode == 200) {
                    // Create user login session
                    Timber.v("feed successful");
                } else {
                    Timber.v("feed failure");
                    Toast.makeText(getApplicationContext(), getResources().getString(R.string.text_login_failed), Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<FeedData> call, Throwable t) {
                Timber.v("onFailure: " + t.getMessage());
            }
        });

ReceivedCookiesInterceptor.java:

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import java.io.IOException;
import java.util.HashSet;

import okhttp3.Interceptor;
import okhttp3.Response;

public class ReceivedCookiesInterceptor implements Interceptor {
private Context context;
public ReceivedCookiesInterceptor(Context context) {
    this.context = context;
} // AddCookiesInterceptor()
@Override
public Response intercept(Chain chain) throws IOException {
    Response originalResponse = chain.proceed(chain.request());

    if (!originalResponse.headers("Set-Cookie").isEmpty()) {
        HashSet<String> cookies = (HashSet<String>) PreferenceManager.getDefaultSharedPreferences(context).getStringSet("PREF_COOKIES", new HashSet<String>());

        for (String header : originalResponse.headers("Set-Cookie")) {
            cookies.add(header);
        }

        SharedPreferences.Editor memes = PreferenceManager.getDefaultSharedPreferences(context).edit();
        memes.putStringSet("PREF_COOKIES", cookies).apply();
        memes.commit();
    }

    return originalResponse;
}
}

AddCookiesInterceptor

import android.content.Context;
import android.preference.PreferenceManager;
import android.util.Log;

import java.io.IOException;
import java.util.HashSet;

import okhttp3.Interceptor;
import okhttp3.Request;
import okhttp3.Response;

/**
 * This interceptor put all the Cookies in Preferences in the Request.
 * Your implementation on how to get the Preferences may vary, but this
 * will work 99% of the time
 */
public class AddCookiesInterceptor implements Interceptor {
public static final String PREF_COOKIES = "PREF_COOKIES";
// We're storing our stuff in a database made just for cookies called PREF_COOKIES.
// I recommend you do this, and don't change this default value.
private Context context;

public AddCookiesInterceptor(Context context) {
    this.context = context;
}

@Override
public Response intercept(Interceptor.Chain chain) throws IOException {
    Request.Builder builder = chain.request().newBuilder();

    HashSet<String> preferences = (HashSet<String>) PreferenceManager.getDefaultSharedPreferences(context).getStringSet(PREF_COOKIES, new HashSet<String>());

    // Use the following if you need everything in one line.
    // Some APIs die if you do it differently.
    //String cookiestring = "";
    //for (String cookie : preferences) {
    //    String[] parser = cookie.split(";");
    //    cookiestring = cookiestring + parser[0] + "; ";
    //}
    //builder.addHeader("Cookie", cookiestring);


    for (String cookie : preferences) {
        builder.addHeader("Cookie", cookie);
    }

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

0 个答案:

没有答案