1、Cookie相关的Http头
有 两个Http头部和Cookie有关:Set-Cookie和Cookie。
Set-Cookie由服务器发送,它包含在响应请求的头部中。它用于在客户端创建一个Cookie
Cookie头由客户端发送,包含在HTTP请求的头部中。注意,只有cookie的domain和path与请求的URL匹配才会发送这个cookie。
下图为Response Header里面的Set-Cookie和 Request Header 里面的 Cookie示例:

1.1、Set-Cookie Header
Set-Cookie响应头的格式如下所示:

1.1.1、expires
expires=<date>: 设置cookie的有效期,如果cookie超过date所表示的日期时,cookie将失效。
如果没有设置这个选项,那么cookie将在浏览器关闭时失效。
注意:date是格林威治时间(GMT)。
1.1.2、domain&path
domain=<domain_name> : path=<some_path>:
注:临时cookie(没有expires参数的cookie)不能带有domain选项。当客户端发送一个http请求时,会将有效的cookie一起发送给服务器。 如果一个cookie的domain和path参数和URL匹配,那么这个cookie就是有效的。
1.1.3、secure
secure : 表示cookie只能被发送到http服务器。
1.1.4、httponly
httponly : 表示cookie不能被客户端脚本获取到。
2、WebView 中的 Cookie机制
WebView是基于webkit内核的UI控件,相当于一个浏览器客户端。它会在本地维护每次会话的cookie(保存在data/data/package_name/app_WebView/Cookies.db)。如下图所示:

通过sqlite工具打开Cookies.db如下图所示:

当WebView加载URL的时候,WebView会从本地读取该URL对应的cookie,并携带该cookie与服务器进行通信。WebView通过android.webkit.CookieManager类来维护cookie。CookieManager是 WebView的cookie管理类。
之前同步cookie需要用到CookieSyncManager类,现在这个类已经被deprecated。如今WebView已经可以在需要的时候自动同步cookie了,所以不再需要创建CookieSyncManager类的对象来进行强制性的同步cookie了。现在只需要获得 CookieManager的对象将cookie设置进去就可以了。
3、使用方法
3.1、写cookie和删cookie
cookie的格式为“key1=value1; key2=value2;”样式的,如下图所示:

设置代码示例如下:
1 2 3 4 |
private static void setCookieValue(String host, String key, String value) { String cookieValue = String.format("%s=%s", new Object[]{key, value}); setCookieValue(host, cookieValue); } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
private static void setCookieValue(String host, String cookieValue) { //注意:没有下面这个判断在4.2,4.3手机会出现jni错误:Call CookieSyncManager::createInstance() or create a webview before using this class if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { CookieSyncManager cookieSyncMngr = CookieSyncManager.createInstance(AppContextHelper.appContext()); cookieSyncMngr.startSync(); doSetCookieValue(host, cookieValue); cookieSyncMngr.stopSync(); } else { doSetCookieValue(host, cookieValue); } } private static void doSetCookieValue(String host, String cookieValue) { try { CookieManager cookieManager = CookieManager.getInstance(); //安全措施,表示cookie不能被客户端脚本获取到。 // cookieManager.setCookie(host, "HttpOnly;"); //Sets whether the application's WebView instances should send and accept cookies. //By default this is set to true and the WebView accepts cookies. cookieManager.setAcceptCookie(true); cookieManager.setCookie(host, cookieValue); } catch (Exception var3) { LogHelper.w(TAG, "setCookie failed:"+var3+", value:"+cookieValue); } } |
如果是删除cookie,则传入的value为“” 空串即可。
3.2、按照域名设置cookies
CookieManager的setCookie方法介绍如下:

此时一种常见的做法是提前为白名单url的host添加cookie,例如百度app里面url可能都有类似的url格式 “http://PREFIX.baidu.com/PATH/PAGE.html?K=V&K2=V2”。我们不需要为每个url都添加cookie,于是我们可以用这样的方式setCookie:
1 |
cookieManager.setCookie(".baidu.com","k=v"); |
其中“.baidu.com” 第一个点”.”符号不能少,它可以通配”XXX.baidu.com”。少了”.”你就无法匹配完整的url了。
注意:如果要为IP写入cookie,就不能在前面加’.’符号了,可以做一个判断:
1 2 3 4 |
//add '.' before host if(!whiteHost.startsWith(".") && !Patterns.IP_ADDRESS.matcher(whiteHost).matches()) { whiteHost = "." + whiteHost; } |
3.3、 立即同步cookie
写完cookie后你希望立即同步cookie可以用到
1、使用CookieSyncManager同步cookie数据:在早期手机硬件性能比较尴尬的时候,为了提升浏览器的性能,加快cookie的读写,浏览器的cookie是存储在手机的内存上的。但是,当当存储在内存上是不够的,还需要保存到存储器上,这时CookieSyncManager应运而生。借助于CookieSyncManager在内存和存储器之间同步浏览器的cookie。另外CookieSyncManager同步策略是在一个独立的线程里定时进行同步。
2、使用CookieManager管理cookie:从sdk21之后,webview已经内置了cookie的同步操作了。虽然不再需要关注cookie的同步,但是依然需要掌握删除cookie的操作。
删除cookie操作:底层实现是异步清除数据库的记录
//非常简洁
CookieManager.getInstance().removeAllCookies(null);
CookieManager.getInstance().flush();
所以出于兼容考虑,我们在写完和删除完cookie后的同步操作代码如下:
1 2 3 4 5 6 7 8 |
private static void flushCookies() { if(Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { CookieSyncManager.createInstance(AppContextHelper.appContext()); CookieSyncManager.getInstance().sync(); } else { CookieManager.getInstance().flush(); } } |