美文网首页
Retrofit使用拦截器添加Cookie

Retrofit使用拦截器添加Cookie

作者: 总会颠沛流离 | 来源:发表于2019-08-11 20:23 被阅读0次

    1. Cookie介绍

    个人理解:cookie其实就是记录用户的一些信息、状态行为等。有这样一种场景,用户在登录成功后,服务端会返回Cookie,里面包含用户的登陆状态信息等,这样用户在访问自己的收藏列表时,加上这个Cookie,那么就可直接获取到文章列表,如果没有Cookie,那服务端怎么知道你是要获取哪个用户的文章列表呢。

    在浏览器上,返回的Cookie会保存在浏览器中,在下次访问时会自动加上该段Cookie,而Android端,需要我们自己来保存服务端返回的Cookie,并在下次访问的时候自己添加上。至于如何保存(Cookie持久化),方法很多,可以用数据库、文件、SharedPreferences、也可以使用Webview的CookieManager。

    大家可以看这篇文章Cookie介绍及在Android中的使用总结超详细,看这一篇就够了

    Cookie访问时添加上其实就是使用header来添加头部信息,在每个需要Cookie的api上都写上头部信息或动态添加,那这样也太繁琐了,接下来我们将通过拦截器来动态添加。

    2. 接口介绍

    本篇文章我将采用Wandroid网站中的登陆接口收藏文章列表接口

    https://www.wanandroid.com/user/login
    方法:POST
    参数:
    username,password

    登录后会在cookie中返回账号密码,只要在客户端做cookie持久化存储即可自动登录验证。

    收藏文章列表

    https://www.wanandroid.com/lg/collect/list/0/json

    方法:GET
    参数: 页码:拼接在链接中,从0开始。

    在网站上登录后,可以直接访问www.wanandroid.com/lg/collect/…查看自己收藏的文章。

    3. Retrofit和OkHttp的关系

    为什么要说OkHttp呢,因为Retrofit底层就是使用OkHttp实现的,只是对其进行了封装,我们可以通过Okhttp中的Interceptor拦截器来设置请求头,然后通过retrofit.client(okhttpclient)对请求头进行修改,这样就省去了我们手动添加请求头的步骤。

    4. 拦截器创建

    这里我们创建两个拦截器,一个用于登录时接收Cookie保存在本地,另一个拦截器用于访问时在请求里添加Cookie。

    4.1 拦截Cookie保存到本地的拦截器

    4.1.1 创建拦截器继承自Interceptor

     public class ReceivedCookiesInterceptor implements Interceptor {
    @Override
    public Response intercept(Chain chain) throws IOException {    
        //拦截的cookie保存在originalResponse中
        Response originalResponse = chain.proceed(chain.request());
        //打印cookie信息
        Log.i(TAG, "intercept: "+ originalResponse.headers("Set-Cookie").toString());
        ...
        return originalResponse;
    }
    }
    

    通过chain.proceed(chain.request())获取到的response内保存了拦截到的cookie信息。
    通过Log.i(TAG, "intercept: "+ originalResponse.headers("Set-Cookie").toString());打印头部信息日志
    我们可以看到网络请求返回的cookie信息,我们要做的就是将这个cookie保存在本地。

    4.1.2 将cookie信息保存在本地

    1:先判断Set-Cookie的头部不为空

    if (!originalResponse.headers("Set-Cookie").isEmpty()) {
    ...
    }

    .######2:通过循环将Cookie信息放入到HashSet集合中

    HashSet<String> cookies = new HashSet<>();
    for(String header: originalResponse.headers("Set-Cookie"))
    {
    cookies.add(header);
    }
    
    3:通过SharePreference将Cookie信息保存在本地
    //保存的sharepreference文件名为cookieData
    SharedPreferences sharedPreferences =     context.getSharedPreferences("cookieData", Context.MODE_PRIVATE);                             
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.putStringSet("cookie", cookies);
    editor.commit()
    

    4.1.3 完整代码

        public class ReceivedCookiesInterceptor implements Interceptor {
    
    public ReceivedCookiesInterceptor() {
        super();
    }
    
    @Override
    public Response intercept(Chain chain) throws IOException {        
        Response originalResponse = chain.proceed(chain.request());
        //这里获取请求返回的cookie
        if (!originalResponse.headers("Set-Cookie").isEmpty()) {
          
            HashSet<String> cookies = new HashSet<>();
            for(String header: originalResponse.headers("Set-Cookie"))
            {
                LogUtil.i(TAG, "拦截的cookie是:"+header);
                cookies.add(header);
            }
           //保存的sharepreference文件名为cookieData
            SharedPreferences sharedPreferences = App.getInstance().getSharedPreferences("cookieData", Context.MODE_PRIVATE);
            SharedPreferences.Editor editor = sharedPreferences.edit();
            editor.putStringSet("cookie", cookies);
    
            editor.commit();
        }
    
        return originalResponse;
    }
    }
    

    4.2 添加本地Cookie进行网络访问的拦截器

    4.2.1 创建拦截器继承自Interceptor
     public class AddCookiesInterceptor implements Interceptor {
    
    @Override
    public Response intercept(Chain chain) throws IOException {       
        ......      
    }
    }
    
    4.2.2 从Sharepreference中读取Cookie并添加到头部
     Request.Builder builder = chain.request().newBuilder();
    
      HashSet<String> perferences = (HashSet)   App.getInstance().getSharedPreferences("cookieData",     Context.MODE_PRIVATE).getStringSet("cookie", null);
      if (perferences != null) {
    for (String cookie : perferences) {
        builder.addHeader("Cookie", cookie);
    }
    }
        return chain.proceed(builder.build());
    

    4.2.3 完整代码

     public class AddCookiesInterceptor implements Interceptor {
    
    @Override
    public Response intercept(Chain chain) throws IOException {
    
        Request.Builder builder = chain.request().newBuilder();
        HashSet<String> perferences = (HashSet) App.getInstance().getSharedPreferences("cookieData", Context.MODE_PRIVATE).getStringSet("cookie", null);
        if (perferences != null) {
            for (String cookie : perferences) {
                builder.addHeader("Cookie", cookie);
            }
        }
        return chain.proceed(builder.build());
    }
    }
    

    5. 应用

    5.1 登录拦截Cookie

    5.1.1 创建OkhttpClient对象
      OkHttpClient client = new OkHttpClient.Builder()
                .addInterceptor(new ReceivedCookiesInterceptor())
                .build();
    
    5.1.2 创建Retrofit对象,并添加此OkhttpClient对象
            private Retrofit retrofitLogin;
            retrofitLogin = new Retrofit.Builder()
                .baseUrl("https://a/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build();
    
    5.1.3 创建接口对象进行访问
    public interface Api {    
    //登录接口
    @FormUrlEncoded
    @POST
    Call<UserBean> login(@Url String url, @FieldMap Map<String, String> param);
    }
    

    ==

      private Api loginApi;
     loginApi = retrofitLogin.create(Api.class);
    

    ======

      Map<String, String> param = new HashMap<>();
      param.put("username", etUsername.getText().toString());
      param.put("password", etPwd.getText().toString());
    
      loginApi.login(loginUrl, param).enqueue(new Callback<UserBean>() {
      @Override
    public void onResponse(Call<UserBean> call, Response<UserBean> response) {
        if (response != null && response.body() != null) {
            if (response.body().getErrorCode() == 0) {
                Toast.makeText(getApplicationContext(), "登录成功", Toast.LENGTH_SHORT).show();} 
            else {
                Toast.makeText(getApplicationContext(), "登录失败" + response.body().getErrorCode() + response.body().getErrorMsg(), Toast.LENGTH_SHORT).show();
            }            
        }
    }
    @Override
    public void onFailure(Call<UserBean> call, Throwable t) {
        Toast.makeText(getApplicationContext(), "登录失败"+t, Toast.LENGTH_SHORT).show();
    }
    });
    } 
    else {
    Toast.makeText(this, "请输入完整的用户信息", Toast.LENGTH_SHORT).show();
    }
    

    5.2 获取收藏列表附加本地Cookie

    5.2.1 创建OkhttpClient对象
       OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .addInterceptor(new AddCookiesInterceptor())
                .build();
    
    5.2.2 创建Retrofit对象,并添加此OkhttpClient对象
          retrofitCollect = new Retrofit.Builder()
                .baseUrl("https://www.wanandroid.com/")
                .addConverterFactory(GsonConverterFactory.create())
                .client(okHttpClient)
                .build();        
    
    5.2.3 创建接口对象进行访问
        public interface Api {
    //获取收藏列表
    @GET("lg/collect/list/{page}/json")
    Call<MyCollectionBean> getCollecEssay(@Path("page") int page);
    }
    

    ========

     private Retrofit retrofitCollect;
    private Api getCollectApi;
    getCollectApi = retrofitCollect.create(Api.class);
    

    ========

     getCollectApi.getCollecEssay(0).enqueue(new Callback<MyCollectionBean>() {
    @Override
    public void onResponse(Call<MyCollectionBean> call, Response<MyCollectionBean> response) {
        if (response != null && response.body() != null) {
            if (response.body().getErrorCode() == 0) {
                Log.i(TAG, "onResponse: 获取文章列表成功");
                for (int i = 0; i < response.body().getData().getDatas().size(); i++) {
                    Log.i(TAG, "\n 收藏的标题名为:" + response.body().getData().getDatas().get(i).getTitle());
                }                
            } else {
                 Log.i(TAG, "onResponse: 获取文章列表失败"+response.body().getErrorMsg());
            }
        }
    }
    @Override
    public void onFailure(Call<MyCollectionBean> call, Throwable t) {
         Log.i(TAG, "onResponse: 获取文章列表失败"+t);
    }
    });
    

    6. 总结

    以上就是全部内容,具体代码见Github
    其实我们使用拦截器的目的就是为了将Cookie信息拦截保存到本地和通过拦截器将Cookie添加到头部信息里,是为了简化我们手动去添加头部信息这一步。
    以上就是全部内容,如果有错误的地方还望指出,。关于Retrofit的图片上传文章还在编辑中,至于怎么用云服务器给大家写个图片上传接口,还在想怎么搞,后台小白一枚,会的大佬麻烦指导指导我。

    7. 参考文章

    Retrofit使用OkHttp保存和添加Cookie

    Android的Cookie的接收和发送

    Cookie介绍及在Android中的使用总结超详细,看这一篇就够了

    相关文章

      网友评论

          本文标题:Retrofit使用拦截器添加Cookie

          本文链接:https://www.haomeiwen.com/subject/qsbqdctx.html