美文网首页
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