美文网首页
Retrofit请求中Cookie的处理

Retrofit请求中Cookie的处理

作者: 刺客的幻影 | 来源:发表于2018-07-10 21:03 被阅读0次
image.png

最近项目重构,登录逻辑大改,安全机制增强,需从初始登录api的响应头里获取Cookie持久化,然后添加到之后api的请求头里,以下是基于Retrofit和Kotlin的实现步骤:

1.获取Cookie

class ResponseInterceptor :Interceptor{
    companion object {
         const val cookie:String = "Set-Cookie"
    }
    override fun intercept(chain: Interceptor.Chain?): Response? {
        val request = chain?.request()?:return null
        val response = chain.proceed(request)
        val cookies  = mutableListOf<String>()
        response.headers("Set-Cookie").run {
            if (isNotEmpty()){
                forEach {
                    cookies.add(it)
                    LogUtil.w("Set-Cookie",it)
                }
                Hawk.put(cookie,cookies)//本地持久化,过期问题此处没处理
            }
        }
        return response
    }
}

首次请求中从响应头中拿到"Set-Cookie",返回的是一个集合cookies,打印出来是这个:
session_name=MTUzMTIyNTQ2MXxOd3dBTkUxQ056SkNWazVQTlROU1NVdFJSMXBZVTFveVJsZEhOek5QVkVGSVZreFpWVm96VGtoQlNWaENWVXREVmpkSlZsSk5Na0U9fHdNeeYckxcr8EpO5j62h6CyLMB4h_gcrR_g7fcE94kU; Path=/; Expires=Wed, 11 Jul 2018 12:24:21 GMT; Max-Age=86400
可以看出这个Cookie中包含4个信息,但是集合大小位1,难道是服务器自己处理拼接成一个了吗 ,分别如下:
- session-name
- Path
- Expires
- Max-Age

2.添加Cookie

class HeaderInterceptor : Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {

        val builder: Request.Builder = chain.request().newBuilder()
        var strigBuilder:StringBuilder ? = null
        Hawk.get<MutableList<String>>(ResponseInterceptor.cookie, mutableListOf())  //取出上一步中存储的Cookie
                .run {
                    if (isNotEmpty()) {
                        forEach {
                            strigBuilder?.append(it)!!.append(";")
                        }
                        strigBuilder?.replace(strigBuilder.length,strigBuilder.length+1,"")//替换掉最后一个";"
                        builder.header("Cookie", strigBuilder.toString())
                    }
                }
        val request = builder.build()
        return chain.proceed(request)
    }
}

3.为Retrofit 里的OkHttpClient添加以上两个拦截器

 private fun initOkHttpClient() {
        val sslParams = HttpsUtils.getSslSocketFactory(arrayOf(okio.Buffer()
                .writeUtf8(ApiConstants.CER_DCOIN).inputStream()), null, null)
        if (mOkHttpClient == null) {
            //设置Http缓存
            val cache = Cache(File(ChainUpApp.appContext.cacheDir, "HttpCache"), (1024 * 1024 * 10).toLong())
            mOkHttpClient = OkHttpClient.Builder()
                    .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)
                    .cache(cache)
                    .addInterceptor(ResponseInterceptor())//获取Cookie的拦截器
                    .addInterceptor(HeaderInterceptor())// 添加Cookie的拦截器
                    .addNetworkInterceptor(CacheInterceptor())
                    .retryOnConnectionFailure(true)
                    .connectTimeout(30, TimeUnit.SECONDS)
                    .writeTimeout(20, TimeUnit.SECONDS)
                    .readTimeout(20, TimeUnit.SECONDS)
                    .protocols(Collections.singletonList(Protocol.HTTP_1_1))
                    .build()
        }
    }

其实Cookie主要应用于Web应用与服务器的交互,但是为了使用同一套接口和安全的考虑,公司的App端也引入了Cookie机制

  • Cookie的用途

因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。最后结帐时,由于HTTP的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么,所以Cookie就是用来绕开HTTP的无状态性的“额外手段”之一。服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。

  • Cookie的缺陷
  1. Cookie会被附加在每个HTTP请求中,所以无形中增加了流量。
  2. 由于在HTTP请求中的Cookie是明文传递的,所以安全性成问题,除非用HTTPS
  3. Cookie的大小限制在4KB左右,对于复杂的存储需求来说是不够用的。

相关文章

网友评论

      本文标题:Retrofit请求中Cookie的处理

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