OkHttp3 (四)——Cookie与拦截器
标签(空格分隔): OkHttp3
版本:1
作者:陈小默
声明:禁止商业,禁止转载
Cookie
在介绍如何使用Cookie之前,我们应该对后台的数据处理有一定的认识。由于HTTP协议无状态的特性,后台是无法保存用户的信息的,在此情形下,Cookie就诞生了。
Cookie的作用是在客户端保存数据,然后在每一次对该站点进行访问的时候都会携带此Cookie中的数据,于是后台就可以通过客户端Cookie中的数据来识别用户。早期很多网站甚至将用户名和密码保存在Cookie中。
在Web应用开发中有一句真理:任何的客户端行为都是不可信赖的。Cookie作为客户端技术,也有着同样的困境。Cookie会被攻击、被篡改,黑客可以从Cookie中查看到用户的用户名和密码,甚至是信用卡的密码。在此情形下,Session的概念被提出。
Session是一种服务端技术。服务端将数据保存在Session中,仅仅将此Session的ID发送给客户端,客户端在请求该站点的时候,只需要将Cookie中的SESSIONID这个数据发送给服务端即可。这样一来就避免了用户信息泄露的尴尬。
接下来我们通过一个具体的例子介绍OkHttp中Cookie的基本使用。
fun login() {
val form = FormBody.Builder()
.add("username", "cxm")
.add("password", "123456")
.build()
val request = Request.Builder()
.url(POST_LOGIN)
.post(form)
.build()
val call = client.newCall(request)
val response = call.execute()
println(response.body().string())
response.close()
}
在上面的登录方法中,我们向服务器发送了用户名和密码,此时在后台的实现是,将用户名和密码保存在服务端的Session中,然后将Session的ID保存在客户端的Cookie中。
fun info() {
val request = Request.Builder()
.url(GET_INFO)
.build()
val call = client.newCall(request)
val response = call.execute()
println(response.body().string())
response.close()
}
在info方法中,后台所做的处理是查询Session中保存的数据,并且返回用户名和密码,如果没有就提示未登录。
OkHttp默认是不保存Cookie的,如果我们需要OkHttp管理Cookie的话,需要给OkHttpClient设置CookieJar对象。
val cookie = object : CookieJar {
private val map = HashMap<String, MutableList<Cookie>>()
override fun saveFromResponse(url: HttpUrl, cookies: MutableList<Cookie>) {
map[url.host()] = cookies
}
override fun loadForRequest(url: HttpUrl): MutableList<Cookie> {
return map[url.host()] ?: ArrayList<Cookie>()
}
}
val client = OkHttpClient.Builder().cookieJar(cookie).build()
saveFromResponse
:方法会在服务端给客户端发送Cookie时调用。此时需要我们自己实现保存Cookie的方式。这里使用了最简单的Map来保存域名与Cookie的关系。
loadForRequest
:每当这个client访问到某一个域名时,就会通过此方法获取保存的Cookie,并且发送给服务器。
接下来我们运行程序
fun main(args: Array<String>) {
login()
info()
}
可以看到如下内容
{"success":true,"message":"login","data":"cxm 登录成功"}
{"success":false,"message":"info","data":"cxm 您好!您的密码是:123456"}
那么当我们没有登录而直接获取信息时
fun main(args: Array<String>) {
//login()
info()
}
就会看到如下的内容
{"success":false,"message":"info","data":"当前未登录,请登陆后再试"}
Android设备中的Cookie持久化
在上面的例子中,我们会发现,由于map并没有被持久化到文件中,每次程序结束时我们存储在map中的Cookie就会消失。如果我们需要在程序每次启动的时候能够使用上次的Cookie,就需要将它序列化到本地文件中。
在Android应用中,我们先创建一个用于网络访问的工具类:
/**
* OkHttp请求工具类
* @author cxm
*/
class HttpUtil(val client: OkHttpClient) {
/**
* 用于回调的Handler