Android客户端如何使用cookie

一. 关于Cookie

一句话概括就是:cookie就是一系列的键值对组成的字符串

二. Cookie的最常用场景

登录状态的判定等

前言

以前看过不少关于cookie的文章,至于写的好坏不做评价,反正我是没看多明白如何操作cookie,也有可能是个人水平不行,无法理解别人的讲解。最近一直在学习后台开发,加上个人一直在做移动端开发,之前一直不明白的地方现在都豁然开朗了,于是打算写这篇文章了。 
如果是在浏览器中,浏览器会管理cookie,不用人为干涉,但是在移动端开发时就不同了,需要手动传递cookie,和服务端交流。如果服务器按照传统的页面开发实现实现接口,那么移动客户端就要实现像浏览器一样操作cookie。

1.想明白如何操作cookie,就必须明白cookie是什么,以及cookie是如何传递的

请求参数: 
这里写图片描述

返回参数: 
这里写图片描述

a)先看响应,返回数据的头中有一系列的key为Set-Cookie的键值对

先说第一个Set-Cookie:JSESSIONID 

JSESSIONID是什么:事实上当用户访问服务器的时候会为每一个用户开启一个session,浏览器是怎么判断这个session到底是属于哪个用户呢?jsessionid的作用就体现出来了:jsessionid就是用来判断当前用户对应于哪个session。换句话说服务器识别session的方法是通过jsessionid来告诉服务器该客户端的session在内存的什么地方。

这时用来实现会话的,如果是第一次访问,请求的参数中没有这个参数,服务器会生成一个JSESSIONID放在响应头中,下次在访问的时候,浏览器就会把这个参数带上 
第一幅图中的Cookie中就有JSESSIONID,这说明已经不是第一次访问了 
而第二幅图中返回的头中有JSESSIONID,说明这次的请求是第一次请求 
这两幅图并不是同一次的请求和响应

第二幅图中的其它Set-Cookie 
都是服务器返回的其它键值对,浏览器不用关心它们是什么意思,下次访问的时候直接在返回给服务端就是。 
其中第二个Set-Cookie长得与其它不太一样,多了一个Expires,这个是表示这个键值对过期时间,如果过期了,下次请求浏览器就不会把这个键值对带过去

b)再看请求:

请求的头中Cookie就是把所有的服务器之前返回的Cookie以分号;进行分割,拼成了一个字符串传给了服务器。 
例如之前服务器响应了JSESSIONID、akey、bkey、ckey四个键值对,再次访问的时候,浏览器就会把没有过期的cookie再次发送给服务器。 
上面提到的akey设置了过期时间,如果akey过期了,那么请求中就不会把akey加到Cookie中。只会发送JSESSIONID、bkey、ckey

c)Cookie的识别

当我们访问的路径地址中包含此cookie的path,则携带。例如:http://localhost:8080/day11/hello,就会把下图中的ckey带着 
这里写图片描述 
path会有一个默认值,过期时间如果不设置,默认就是关闭浏览器时过期

2.利用HttpURLConnection操作Cookie,模拟浏览器

a)获取Cookie

getHeaderFields()方法,返回结果是Map<String,List<String>>类型

HttpURLConnection httpConn = null;

...

Map<String,List<String>> cookies = httpConn.getHeaderFields();

List<String> setCookies = cookies.get("Set-Cookie");

这样就可以吧所有的Set-Cookie字段都拿到。存起来,至于怎么存,无所谓,自己决定

b)携带Cookie

// 把你存的Cookie键值对用分号分隔,拼成一个字符串,是不是需要把所有Cookie都拼进来,看实际情况

// 例如你有10个键值对,有3个过期的,肯定不要了,至于过期判定,前面有说到,这个就需要你按照规定的格式判断出来。还有两个可能是这次请求不需要的,也可以不带,为了简单可以直接把所有没过期的都带上,省事,服务器爱用不用。

String cookie = "JSESSIONID=xxx;key1=value1;key2=value2"

conn.setRequestProperty("Cookie", cookie);

这样就可以传给服务器,就是在和么简单。

c)会话保持 
拿到的Cookie中如果有JSESSIONID就存起来,每次请求都带着,这样就能实现保持会话,如果某次请求服务器告诉你需要重新新登录了,那么你就把保存的JSESSIONID删了,并且请求中不携带JSESSIONID,服务器会再给你一个新的,保存下来以后继续用即可。

三、Cookie在Android中的持久化

持久化保存cookie有很多方式,可以用数据库,可以用文件,SharedPreferences,还可以保存到系统Webview的CookieManager里(其实也是个数据库)。

如果我们自己本地保存cookie,要做好本地Cookie和Webview的cookie同步,所以最好的办法是把本地请求获得的Cookie也保存到系统Webview的CookieManager里,取的时候从Webview的CookieManager里取,让CookieManager统一管理岂不美滋滋,哈哈。

PersistentCookieJar是一个持久化在SharedPreferences中的例子,代码也不复杂,大家可以看看:
https://github.com/franmontiel/PersistentCookieJar A persistent CookieJar implementation for OkHttp 3 based on SharedPreferences.

OkHttp3.0 中实现 Cookie 持久化管理
3.0之后OKHttp是加了CookieJar和Cookie两个类的,通过实现CookieJar即可管理cookie。

private class CookiesManager implements CookieJar {

    private final PersistentCookieStore cookieStore = new PersistentCookieStore(getApplicationContext());

    @Override
    public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
        if (cookies != null && cookies.size() > 0) {
            for (Cookie item : cookies) {
                cookieStore.add(url, item);
            }
        }
    }

    @Override
    public List<Cookie> loadForRequest(HttpUrl url) {
        List<Cookie> cookies = cookieStore.get(url);
        return cookies;
    }
}

OkHttpClient.Builder builder = new OkHttpClient.Builder();
builder.cookieJar(new CookiesManager());


WebView中的Cookie机制
WebView是基于webkit内核的UI控件,相当于一个浏览器客户端。它会在本地维护每次会话的cookie(保存在data/data/package_name/app_WebView/Cookies),如下图:

å¨è¿éæå¥å¾çæè¿°
数据就保存在Cookies那个文件里,其实是个数据库,把后缀改成.db用数据库打开可以看到里面的表结构,主要有host_key, name, value, path等,host_key其实就是前面说的domain,这些字段其实也都是前面说的属性:

å¨è¿éæå¥å¾çæè¿°
当WebView加载URL的时候,WebView会从本地读取该URL对应的cookie,并携带该cookie与服务器进行通信。WebView通过android.webkit.CookieManager类来维护cookie。CookieManager是 WebView的cookie管理类。

之前同步cookie需要用到CookieSyncManager类,现在这个类已经被deprecated。如今WebView已经可以在需要的时候自动同步cookie了。

CookieSyncManager

在安卓5.0以下,主要使用CookieSyncManager在内存和存储器之间同步浏览器的cookie,另外CookieSyncManager同步策略是在一个独立的线程里定时进行同步。

cookie开始同步:注意每次同步的时间间隔是5分钟

CookieSyncManager.createInstance(context); 
CookieSyncManager.getInstance().startSync();

cookie停止同步:

CookieSyncManager.getInstance().stopSync()

cookie立即同步:调用了该方法会立即进行cookie的同步,代码如下:

//一般是在webview中的onPageFinished(WebView, String)方法进行强制同步
CookieSyncManager.getInstance().sync()


删除cookie操作:

CookieSyncManager.createInstance(this); 
CookieManager.getInstance().removeAllCookie(); 
CookieManager.getInstance().removeSessionCookie();
CookieSyncManager.getInstance().sync(); 

CookieManager

从5.0之后,webview已经内置了cookie的同步操作了。

删除所有Cookie

CookieManager.getInstance().removeAllCookies(null); 
CookieManager.getInstance().flush();


保存Cookie

CookieManager.getInstance().setCookie(String url, String value)


获取Cookie

CookieManager.getInstance().getCookie(url)


我们综合两个Manager, 最后写法:

同步Cookie

CookieSyncManager.createInstance(this); 
if (Build.VERSION.SDK_INT < 21) {
    CookieSyncManager.getInstance().sync();
} else {
    CookieManager.getInstance().flush();
}


删除所有Cookie

CookieSyncManager.createInstance(this); 
CookieManager.getInstance().removeAllCookie(); 
CookieManager.getInstance().removeSessionCookie(); 
if (Build.VERSION.SDK_INT < 21) {
    CookieSyncManager.getInstance().sync();
} else {
    CookieManager.getInstance().flush();
}

总结,Cookie本身就是键值对,key是Cookie,value是各种cookie中间用分号分隔的字符串,每个value分号分隔的里面又是键值对,name是某个cookie的名称,value是具体的cookie的值。在浏览器的请求头中会自动传给服务端,其实传的是多个Cookies,后端从中根据name取出你需要的即可。不过我不太建议使用Cookie来保存用户的登录状态,在移动端ios和安卓是可以的,但是如果在web端,用户的浏览器是禁用的,而我们的鉴权可能又是使用的一套,就会有些麻烦了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值