Android实现清除单个域名的cookie

今天PM提了个需求:用户退出当前网页时,只清除该网页访问的域名相关的cookie,保留其他域名的cookie。

查了一下CookieManager的API,发现只有removeAllCookie(),没有清除单独域名cookie的API。。。想想也是,用了这么多年的浏览器,啥时候见过这功能?

既然系统没有提供接口,那就是只能自己想办法去清了。

首先要搞清楚Cookie存在哪里吧?

在/data/data/<package>/app_webview目录下,找到一个Cookies文件,虽然它没有.db扩展名,但是其实它就是一个sqlite数据库!进去看一下,数据都存在里面的cookies表里:

sqlite> .tables
cookies meta
sqlite> .dump cookies
PRAGMA foreign_keys=OFF;
BEGIN TRANSACTION;
CREATE TABLE cookies (creation_utc INTEGER NOT NULL UNIQUE PRIMARY KEY,host_key TEXT NOT NULL,name TEXT NOT NULL,value TEXT NOT NULL,path TEXT NOT NULL,expires_utc INTEGER NOT NULL,secure INTEGER NOT NULL,httponly INTEGER NOT NULL,last_access_utc INTEGER NOT NULL, has_expires INTEGER NOT NULL DEFAULT 1, persistent INTEGER NOT NULL DEFAULT 1,priority INTEGER NOT NULL DEFAULT 1,encrypted_value BLOB DEFAULT '',firstpartyonly INTEGER NOT NULL DEFAULT 0);
INSERT INTO "cookies" VALUES(13122904895970126,'.hm.baidu.com','HMACCOUNT','1E0666871DC4BB45','/',13792186776970126,0,0,13122906283432123,1,1,1,X'',0);
INSERT INTO "cookies" VALUES(13122905170226445,'.facebook.com','reg_fb_ref','https%3A%2F%2Fm.facebook.com%2F%3Frefsrc%3Dhttps%253A%252F%252Fwww.facebook.com%252F','/',0,0,1,13122905170226445,0,0,1,X'',0);
INSERT INTO "cookies" VALUES(13122905170227182,'.facebook.com','reg_fb_gate','https%3A%2F%2Fm.facebook.com%2F%3Frefsrc%3Dhttps%253A%252F%252Fwww.facebook.com%252F','/',0,0,1,13122905170227182,0,0,1,X'',0);
INSERT INTO "cookies" VALUES(13122905170227393,'.facebook.com','m_ts','1478103992','/',0,0,0,13122905170227393,0,0,1,X'',0);
INSERT INTO "cookies" VALUES(13122905172258460,'.facebook.com','datr','uxMaWFe4eAqp6W2_dDu2MpA1','/',13185977172258460,0,1,13122905172258460,1,1,1,X'',0);
INSERT INTO "cookies" VALUES(13122905172508865,'.facebook.com','fr','0EhMpmXi6717eJE6Y..BYGhO4.Dd.AAA.0.0.BYGhO7.AWUFjMmY','/',13130681172508865,0,1,13122905172508865,1,1,1,X'',0);
CREATE INDEX domain ON cookies(host_key);
CREATE INDEX is_transient ON cookies(persistent) where persistent != 1;
COMMIT;

这里面存储的其实就是HTTP头里的Set-Cookie字段包含的所有信息,以facebook为例,拼起来其实就是:

Set-Cookie: m_ts=1478103992; datr=uxMaWFe4eAqp6W2_dDu2MpA1; fr=OEhMpmXi6717eJE6Y; path=/; domain=.facebook.com

只要我们把这些信息清除掉,webview下次发请求的时候就没有有效cookie了。最直接的想法,调用CookieManager的setCookie()方法,把这些字段清空或者设置为过期不就行了?在StackOverflow上搜了一下,找到一个帖子讨论类似的思想,试了一下发现还是不行。。。

原文链接:http://stackoverflow.com/questions/2834180/how-to-remove-cookies-using-cookiemanager-for-a-specific-domain/11621738#11621738

下面说一说遇到的一堆坑吧:

1. 同一个域名,http跟https两种情况下cookie带的参数是不一样的。举个例子,http://www.facebook.com跟https://www.facebook.com,通过CookieManager.getCookie()获取 的参数是完全不一样的。这个问题困扰了我一个多小时,因为我发现有些参数死活清不掉。。。

2. Cookies表里有一堆以“.”开头的域名,比如表里的那个“.facebook.com”,它的一些参数用完全域名删不掉。比如针对http://www.facebook.com调用CookieManager.setCookie()清除字段信息,你会发现表里多了一项"www.facebook.com"的记录,而原来的".facebook.com"的记录仍然存在而且字段信息没有被清除。

3. 使用以“.”开头的域名,比如".facebook.com",调用CookieManager.getCookie()时获取不到全的参数列表。

4. 不同的网站会在Cookies表里增加多项记录,以facebook为例,表里可能会存"www.facebook.com"、".www.facebook.com"、".facebook.com"这3种记录。

最后说结论吧,几经周折,总算找到一个能用的方法,亲测5.1 / 6.0平台可用。其实也很简单粗暴,就是把上面第4条提到的那几种记录统统撸一遍,宁可错杀一千,也不放过一个。。。

附上代码(注意domain参数是带上协议的全域名,比如https://www.baidu.com):

private static void deleteCookiesForDomain(Context context, String domain) {
    CookieManager cookieManager = CookieManager.getInstance();
    if (cookieManager == null) return;

    /* http://code.google.com/p/android/issues/detail?id=19294 */
    if (Build.VERSION.SDK_INT < 11) {
      /* Trim leading '.'s */
      if (domain.startsWith(".")) domain = domain.substring(1);
    }

    String cookieGlob = cookieManager.getCookie(domain);
    if (cookieGlob != null) {
      String[] cookies = cookieGlob.split(";");
      for (String cookieTuple : cookies) {
        String[] cookieParts = cookieTuple.split("=");
        HashSet<String> domainSet = getDomainSet(domain);
        for (String dm : domainSet) {
          /* Set an expire time so that this field will be removed after calling sync() */
          cookieManager.setCookie(dm, cookieParts[0] + "=; Expires=Wed, 31 Dec 2015 23:59:59 GMT");
        }
      }
      cookieManager.sync();
    }
  }

  private static HashSet<String> getDomainSet(String domain) {
    HashSet<String> domainSet = new HashSet<>();
    String host = Uri.parse(domain).getHost();

    domainSet.add(host);
    domainSet.add("." + host);
    // exclude domain like "baidu.com"
    if (host.indexOf(".") != host.lastIndexOf(".")) {
      domainSet.add(host.substring(host.indexOf('.')));
    }

    return domainSet;
  }

以上这篇Android实现清除单个域名的cookie就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Android中webView加载H5绑定cookie实例

    简介: 我最近在做项目的时候遇到了这种情况: 1.需要用WebView实现一个H5的登陆注册. 2.大赛报名,用H5实现.这些情况下,我需要把cookie传给服务器,让其判断当前账户是否登陆成功.查阅了一些资料后,终于搞定了. 1. 给一个加载的链接设置cookie private void syncCookie(String url) { try { CookieSyncManager.createInstance(mWvSignUp.getContext());//创建一个cookie管理器

  • Android实现清除单个域名的cookie

    今天PM提了个需求:用户退出当前网页时,只清除该网页访问的域名相关的cookie,保留其他域名的cookie. 查了一下CookieManager的API,发现只有removeAllCookie(),没有清除单独域名cookie的API...想想也是,用了这么多年的浏览器,啥时候见过这功能? 既然系统没有提供接口,那就是只能自己想办法去清了. 首先要搞清楚Cookie存在哪里吧? 在/data/data/<package>/app_webview目录下,找到一个Cookies文件,虽然它没有.

  • nginx+tomcat单个域名及多个域名配置教程

    项目开发接近尾声,开始着手在生产环境部署项目,开发阶段部署项目都没用nginx.项目是采用SOA架构,多系统开发,主要包括服务系统.中台系统.后台系统.金融系统.接口系统.调度系统.报表系统等.这类分布式的系统,一般也都会用到nginx来做负载均衡. 从公司刚成立就进来,赶鸭子上架来做架构师,负责公司的所有研发事情,搭建公司的整个技术架构,起初的所有核心业务代码基本都由自己亲自把关来进行编码.系统也从最初的只有一个pc端,发展到如今pc中台.后台.android端3个app.iOS端3个app,

  • Android彻底清除APP数据的两种方案总结

    目录 用途 方案一:利用命令行pm clear 包名,系统级别清除App数据 优点 缺点 代码 方案二:手动删除内部储存和外部储存 优点 缺点 代码 总结 用途 用于APP内部的重置功能实现. 方案一:利用命令行pm clear 包名,系统级别清除App数据 优点 和任务管理器里面清除所有数据的操作一致,会删除所有的APP数据.重新进入APP还需重新申请权限. 缺点 系统会直接杀掉APP进程,无法进行拉起APP的操作. 代码 public static Process clearAppUserD

  • 域名和cookie问题(域名后缀)

    域名和cookie 偶然想到一个问题:www.g.cn能把cookie设置为.g.cn,那么www.com.cn能设置把cookie设置为.com.cn吗? 试验结果:不能.因为浏览器知道www.com.cn的后缀是.com.cn而不是.cn,所以禁止设置cookie. 因为浏览器内置了域名后缀列表.todo:如果以后出现新的后缀,而老浏览器没法更新列表,岂不是会允许设置cookie? extension后缀 一级域名 二级域名 www.g.cn .cn g.cn *.g.cn www.com.

  • Android 带清除功能的输入框控件实例详解

    Android 带清除功能的输入框控件实例详解 今天,看到一个很好的自定义输入框控件,于是记录一下. 效果很好: 一,自定义一个类,名为ClearEditText package com.example.clearedittext; import android.content.Context; import android.graphics.drawable.Drawable; import android.text.Editable; import android.text.TextWatc

  • python爬虫之遍历单个域名

    即使你没听说过"维基百科六度分隔理论",也很可能听过"凯文 • 贝肯 (Kevin Bacon)的六度分隔值游戏".在这两个游戏中,目标都是把两 个不相干的主题(在前一种情况中是相互链接的维基百科词条,而在后 一种情况中是出现在同一部电影中的演员)用一个链条(至多包含 6 个 主题,包括原来的两个主题)连接起来. 比如,埃里克 • 艾德尔和布兰登 • 弗雷泽都出现在电影<骑警杜德雷> 里,布兰登 • 弗雷泽又和凯文 • 贝肯都出现在电影<我呼吸的空

  • Android带清除按钮、密码可见小眼睛的输入框

    前言 相信不少小伙伴在开发登录功能时候,或多或少都会用到输入框清除按钮.密码可见与隐藏小眼睛按钮,我之前也是但写这个功能,但是在找回密码.忘记密码里面还要重新写一次很是麻烦,现在我把它只做了一个自定义控件,可以配置清除按钮.密码可见小眼睛是否显示以及图标,有渐隐渐显和横向移动动画,不知道怎么上传可以直接观看的视频,附上三张效果图,可以点击链接观看视频是否是你想要的效果.   一.自定义控件ClearEditText 我的这个自带清除.小眼睛的控件,是一个自定义控件,控件名称ClearEditTe

  • Android带清除功能的输入框控件EditTextWithDel

    记录下一个很实用的小控件EditTextWithDel,就是在Android系统的输入框右边加入一个小图标,点击小图标可以清除输入框里面的内容,由于Android原生EditText不具备此功能,所以要想实现这一功能我们需要重写EditText. 效果图如下: 主要的思路就是为右边的图片设置监听,点击右边的图片清除输入框的内容并隐藏删除图标,因为我们不能直接给EditText设置点击事件,所以我们用记住我们按下的位置来模拟点击事件,用输入框的的onTouchEvent()方法来模拟. packa

  • Android实现清除应用缓存功能

    本文实例为大家分享了Android清除应用缓存的具体代码,供大家参考,具体内容如下 import android.content.Context; import android.os.Environment; import java.io.File; import java.math.BigDecimal; /** * 获取缓存大小并清理缓存 */ public class DataCleanManagerUtils { /** * Context.getExternalFilesDir() -

  • 指定js可访问其它域名的cookie的方法

    和路径类似,主机名是指同一个域下的不同主机,例如:www.sosuo8.com和blog.sosuo8.com就是两个不同的主机名.默认情况下,一个主机中创建的cookie在另一个主机下是不能被访问的,但可以通过domain参数来实现对其的控制,其语法格式为: document.cookie="name=value;domain=cookieDomain"; 以sosuo8为例,要实现跨主机访问,可以改写为: document.cookie="name=value;domai

随机推荐