1. 程式人生 > >Retrofit2.0+Gson+RxJava 框架 之 Session保持(解決Session無效問題) 【Android】

Retrofit2.0+Gson+RxJava 框架 之 Session保持(解決Session無效問題) 【Android】

       Retrofit2.0中,每個請求之間是獨立開的,這產生一個問題,也就是如何保持Session資訊,更通俗易懂的說,就是如何保持登入狀態,如果不做任何操作,那麼不管登入多少次,都是無效的,無法進行其他許可權操作。這裡要提交到瀏覽器,瀏覽器是預設自動儲存伺服器傳送過來的Session資訊的,也就是預設保持Session資訊的,只有當瀏覽器關閉,才會清除這些Session資訊。

     說到這裡,你可能會說Session不是儲存在伺服器的嗎?注意,這裡用的是“保持”,換一種說法,就是讓伺服器知道這還是你,而不是新的使用者連線。

Session 機制:

一般來說,伺服器使用Session來判斷使用者是否登入,也就是:

       當伺服器與客戶建立新的連線時,會建立一個會話Session,每個使用者的Session的id都是不一樣的,這是識別每個客戶的一個id,當建立客戶的Session後會放在響應體Response的頭部資訊中,具體位置為:

也就是Cookie的第一個字元到第一個;之間,注意,這是一個key-value,我們只需要在登入後返回的Response的頭部將這一串資訊拿下,並在以後每一次請求中,在Cookie加入這一串Session資訊,即可實現Session保持,或者說 保持登入狀態。

實現步驟:

 1.導包

      匯入攔截器,主要作用是:1.攔截每一次請求。2.在攔截的請求中的Cookie中加入Session資訊。

  compile 'com.squareup.okhttp3:logging-interceptor:3.8.1'

2.在第一次請求的響應體中,從Cookie中拿出Session資訊。如下:

      主要程式碼:

public class UserController {
    public static UserService userService= RetrofitFactory.createRetrofit().create(UserService.class);
    public static void login(String username, String password, final NetCallback callback) {
        Map<String,Object> map=new HashMap<>();
        map.put("userId",username);
        map.put("password",password);
        Call<ResponseBody> call=userService.login(map);
        call.enqueue(new Callback<ResponseBody>() {
            @Override
            public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if(response.isSuccessful()){
                    try {
                        HeaderInterceptor.cookie=response.headers().get("set-cookie");
                        Log.e("NetWork=>headers", HeaderInterceptor.cookie);
                        callback.onSuccess(new Gson().fromJson(response.body().string(), ValidateResult.class));
                    } catch (IOException e) {
                        callback.onError(10001);
                    }
                }
                else{
                   Log.e("NetWork",response.message());
                }
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Log.e("NetWork",t.getLocalizedMessage());
                callback.onError(10002);
            }
        });
    }
}

      其中:獲取如下:

public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
                if(response.isSuccessful()){
                    try {
                        HeaderInterceptor.cookie=response.headers().get("set-cookie");
                        Log.e("NetWork=>headers", HeaderInterceptor.cookie);
                        callback.onSuccess(new Gson().fromJson(response.body().string(), ValidateResult.class));
                    } catch (IOException e) {
                        callback.onError(10001);
                    }
                }
                else{
                   Log.e("NetWork",response.message());
                }
            }

      使用 response.headers().get('set-cookie");獲取cookie資訊,並將其儲存下來,這裡儲存在自定義攔截器HeaderInterceptor裡面.

3.建立攔截器HeaderInterceptor

      程式碼如下:

public class HeaderInterceptor implements Interceptor {
    //儲存cookie
    public static String cookie=null;
    @Override
    public Response intercept(Chain chain) throws IOException {
        Request request = chain.request();
        Request.Builder builder = request.newBuilder();
        if(cookie!=null) {
            builder.addHeader("Cookie", cookie);
            if (Build.VERSION.SDK != null && Build.VERSION.SDK_INT > 13) {
                builder.addHeader("Connection", "close");
            }
        }
        else{
            Log.e("Cookie","Cookie not found");
        }
        return chain.proceed(builder.build());
    }
}

4.測試。

(完)