浅谈用户行为分析之用户身份识别:cookie 知多少?

标签: 日志采集与架构 | 发表时间:2015-10-25 19:31 | 作者:
出处:http://my.oschina.net/leejun2005

对于数据统计分析或者数据挖掘而言,用户是个非常重要的维度,也是统计分析能落地的基础。一般而言,咱们追踪或者识别一个用户的首选方案是 userID,大多数公司的产品都会要求用户注册、登录操作,都存在一个类似 UMC 的数据库,管理和标示所有的用户。但这有个前提条件,就是你所在的公司业务必须以闭环为主(比如 qq、微信、淘宝等)。如果产品没有形成闭环,用户就不会主动去注册、登录,那上面通过 userID 数据库来管理、追踪用户行为的方案就不行了。比如BBS站点或者广告联盟都会非常想要一种技术方式可以在网络上精确定位到每一个个体,这样可以通过收集这些个体的数据,通过分析后更加精准的去推送广告(精准化营销)或其他有针对性的一些活动。当用户访问一个网站时,网站生成一个含有唯一标示符(UUID)的信息,并通过这个信息将用户所有行为(浏览了哪些页面?搜索了哪些关键字?对什么感兴趣?点了哪些按钮?用了哪些功能?看了哪些商品?把哪些放入了购物车等等)关联起来。那这种情况下有没有可能有其它的技术方案去管理追踪这种游客态用户呢?

答案或许很多同学会回答用 cookie。是的,对于游客态用户而言,常用的身份识别方案就是使用 cookie,技术实现难度小,成本相对很低廉。那是不是使用 cookie 就万事大吉了呢?准确性、稳定性、可辨识性怎么样?下面咱们就来深入探讨下 cookie 追踪用户的利弊及其发展与移动互联网时代下用户身份识别面临的新问题。

1、追踪/标示用户的方法

先上一张图,可以看到大部分流行的方法还是基于Cookie,只是这些 Cookie 会稍有不同,本文会按照整张图的脉络来一一介绍各种 cookie 及其利与弊。

2、HTTP Cookie

2.1 由来

为什么会有 HTTPCookie 呢?因为HTTP协议是无状态的,即服务器不知道用户上一次做了什么,这严重阻碍了交互式Web应用程序的实现。在典型的网上购物场景中,用户浏览了几个页面,买了一盒饼干和两瓶饮料。最后结帐时,由于HTTP的无状态性,不通过额外的手段,服务器并不知道用户到底买了什么。 所以Cookie就是用来绕开HTTP的无状态性的“额外手段”之一。服务器可以设置或读取Cookies中包含信息,借此维护用户跟服务器会话中的状态。

2.2 实现方式

Cookie是由服务器端生成(webserver或者cgi),response 给User-Agent(一般是浏览器),浏览器会将Cookie的key/value保存到某个目录下的文本文件内,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。

2.3 缺陷

  • Cookie会被附加在每个HTTP请求中,所以无形中增加了流量。

  • 由于在HTTP请求中的Cookie是明文传递的,所以安全性成问题。(除非用HTTPS)

  • Cookie的大小限制在4KB左右。对于复杂的存储需求来说是不够用的。

  • 浏览器安全策略不允许种植 cookieID、用户清除 cookieID,不同的浏览器也会生成不同的 cookieID,大量的爬虫也可能带上随机 cookieID

  • 识别不准确:浏览器安全策略不允许种植 cookieID、用户清除 cookieID,不同的浏览器生成不同的 cookieID,大量的爬虫带上随机 cookieID

3、Flash Cookie

3.1 由来

在客户端Cookie里保存数据是不稳 定的,因为用户可能随时会清除掉浏览器的Cookie,在这种情况下,一般的解决方案是重新向服务器端发送一个请求,以获得一个新的HTTP Cookie数据,并将其保存,就一般的交互需求而言,这是没有问题的。但是,倘若我的需求是:要求恢复到原来的Cookie里保存数据持久的追踪用户的行为呢?这种情况,倘若服务器端没有做特殊的处理的话,显然是很难实现的,这里就该 Flash Cookie 登场了。

FlashCookie是由FlashPlayer控制的客户端共享存储技术,它具备以下特点:

  • 类似 HTTPCookie,FlashCookie利用SharedObject类实现本地存储信息,SharedObject类用于在用户计算机上读取和存 储有限的数据量,共享对象提供永久贮存在用户计算机上的对象之间的全局实时数据共享;

  • 本地共享对象是作为一些单独的文件来存储的,它们的文件扩展名 为.SOL。默认时,它们的尺寸为不超过100kB,并且不会过期——这一点与传统的HTTP Cookie不同(4KB);

  • 本地共享对象并不是基于浏览器的,所以普通的用户不容易删除它们。如果要删掉它们的话,首先要知道这些文件所在的具体位 置。这使得本地共享对象能够长时间的保留在本地系统上。

3.2 实现方式

要实现Flash Cookie永远存储的功能,显然,首先要实现Flash Cookie与Http Cookie的互通,所以,在技术上使用JavaScript与ActionScript的来进行沟通显然是最好的选择,因为在这两种语言之间,除了语法 上相近,从沟通上也有着完美的实现。下面我们来看看实现流程(如图所示):

这里给一个实现的 demo,点窗口→动作,我们就可以写actionscript3的代码了,然后文件→发布成 .swf 文件:

//导入ExternalInterface类
import flash.external.ExternalInterface;

flash.system.Security.allowDomain("http://localhost");
flash.system.Security.allowDomain("http://127.0.0.1");
//允许任何域都可以访问
flash.system.Security.allowDomain("*");

function setFC(userName:String, sex:String) {
    var FlashCookie:SharedObject = SharedObject.getLocal("testFlashCookie");
    FlashCookie.data.cookie["userName"] = userName;
    FlashCookie.data.cookie["sex"] = sex;
    FlashCookie.flush();
}
function getFC():String {
    var FlashCookie:SharedObject = SharedObject.getLocal("testFlashCookie");
    return FlashCookie.data.cookie["userName"];
}
function setFCUserObj(obj:Object) {
    var FlashCookie:SharedObject = SharedObject.getLocal("testFlashCookie");
    if (FlashCookie.data.cookie == undefined) {
        //var obj:Object = {};
        //obj[key] = value;
        FlashCookie.data.cookie = obj;
    } else {
        for (var key:String in obj) {
            FlashCookie.data.cookie[key] = obj[key];
        }

    }
    //FlashCookie.data.userName = obj.userName;
    //FlashCookie.data.sex = obj.sex;
    FlashCookie.flush();
}
//允许js)调用flash中的getFC(),setFC(),setFCUserObj
ExternalInterface.addCallback("getFC", getFC);
ExternalInterface.addCallback("setFC", setFC);
ExternalInterface.addCallback("setFCUserObj", setFCUserObj);

再用 flask 搭一个简单的页面:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="zh-CN">
<head>
    <title>testFC</title>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <style type="text/css" media="screen">
        html, body {
            height: 100%;
            background-color: #ffffff;
        }

        body {
            margin: 0;
            padding: 0;
            overflow: hidden;
        }

        #flashContent {
            width: 100%;
            height: 100%;
        }
    </style>
    <script type="application/javascript">
        function setCookie(c_name, value, expiredays) {
            var exdate = new Date()
            exdate.setDate(exdate.getDate() + expiredays)
            document.cookie = c_name + "=" + escape(value) +
                    ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString())
        }
        function getCookie(c_name) {
            if (document.cookie.length > 0) {
                c_start = document.cookie.indexOf(c_name + "=")
                if (c_start != -1) {
                    c_start = c_start + c_name.length + 1
                    c_end = document.cookie.indexOf(";", c_start)
                    if (c_end == -1) c_end = document.cookie.length
                    return unescape(document.cookie.substring(c_start, c_end))
                }
            }
            return ""
        }

    </script>

    <script type="text/javascript">
        //搭建js与flash互通的环境
        function thisMovie() {
            if (navigator.appName.indexOf("Microsoft") != -1) {
                return window["testFC"];
            } else {
                return document["testFC"];
            }
        }

        function setFCUseObj() {
            c_name = getCookie("userName")
            c_sex = getCookie("sex")
            if (c_name == "") {
                alert("当前 jCookie: " + c_name + "\n" + "当前 flash cookie: " + thisMovie().getFC())
                var ajaxRequest = new XMLHttpRequest();
                ajaxRequest.open("GET", "http://127.0.0.1:5000/add", false);
                ajaxRequest.send(null);
                c_name = getCookie("userName") + Math.random();
                c_sex = getCookie("sex") + Math.random();
            }
            {#            expiredays = 1#}
            {#            setCookie(key, value, expiredays)#}
            var obj = new Object();
            obj.userName = c_name;
            obj.sex = c_sex;
            thisMovie().setFCUserObj(obj);
        }
        function getFC() {
            alert(thisMovie().getFC());
        }
        function setFC() {
            thisMovie().setFC("June_flashCookie", "male");
        }

    </script>
</head>

<body>
<input type="button" onclick="setFC()" value="setFC"/>
<input type="button" onclick="getFC()" value="getFC"/>
<input type="button" onclick="setFCUseObj()" value="setFCUseObj"/>

<div id="flashContent">
    <object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000"
            codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0" width="1"
            height="1" id="testFC" title="testFC">
        <param name="allowScriptAccess" value="always"/>
        <param name="movie" value="testFC.swf">
        <param name="quality" value="high">
        <param name="wmode" value="transparent"/>
        <embed src="static/testFC.swf" name="testFC" quality="high" allowScriptAccess="always" swLiveConnect="true"
               pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="1"
               height="1"></embed>
    </object>
</div>
</body>
</html>

最后再配个简单的 cgi:

from flask import Flask, request, Response, make_response, render_template
import time

app = Flask(__name__)


@app.route('/')
def hello_world():
    return 'hello world'


@app.route('/add')
def login():
    res = Response('add cookies')
    res.set_cookie(key='userName', value='lisi_jsCookie', expires=time.time() + 10 * 60)
    res.set_cookie(key='sex', value='unKnown', expires=time.time() + 10 * 60)
    return res


@app.route('/testFC')
def cookietest():
    return render_template("testFC.html")

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

3.3 缺陷

优势是显而易见的,缺陷在于:

  • 部署相对 HTTP Cookie 复杂了,存在一定的开发维护成本。

  • 兼容性不够好,目前只支持特定的平台与特定的浏览器,比如 苹果的全系列产品都不支持 flash,以至于2012年开始 adobe 已经彻底放弃了移动端 flash 的更新,这样 Android 未来也不会存在 flash 这一技术了。

  • 可以跨浏览器使用,只要浏览器调用的是同一个Flash组件(如Internet Explorer和Mozilla Firefox之间信息便可共享,但Google Chrome和Mozilla Firefox便不行)。

  • 虽然可以跨浏览器,但隐身模式无效。可以被很容易地清除。

4、EverCookie

4.1 由来

前面的两种方法都存在一定的缺陷,在复杂多变的用户场景里,数据可能和真实的误差很大,那有没有办法进一步提高 Cookie 追踪用户身份的准确度呢?也有,那就是最后聊到的 EverCookie,其实它也不是什么新的 cookie 技术,只是利用客户端各种存储区域,尽可能的存储多的 cookie 副本,以防某处 cookie 被删除可以恢复,相当于 cookie 也有了类似 hadoop 多副本灾备机制,同时生成 cookieID 的算法参考了更多的客户端标识和软硬件特征,让 cookieID 具有更高的稳定性、唯一性、可辨识性,不随算法本身随机性的影响。

4.2 实现方式

Evercookie不仅仅是难删除,而是会积极“反抗”删除。方法就是在用户电脑里,利用不同的存储机制不断地复制自己,或者在副本丢失或到期作废时让自己重新复活。具体来说,Evercookie在创建cookie时会使用如下存储机制:

  • 标准HTTP cookie

  • Local Shared Objects (Flash cookie)

  • Silverlight Isolated Storage

  • 以自动生成、强制缓存的PNG像素图片的RGB值形式保存cookie,使用HTML5 Canvas标签读取像素图片(cookie)

  • 在浏览器历史记录中存储cookie

  • 在HTTP ETag中存储cookie

  • 在浏览器缓存中存储cookie

  • window.name缓存

  • Internet Explorer userData

  • HTML5 Session Storage

  • HTML5 Local Storage

  • HTML5 Global Storage

  • HTML5 Database Storage(SQLite)

开发人员计划增加如下功能:

  • HTTP Authentication缓存

  • 使用Java基于NIC信息产生唯一键

4.3 缺陷

上面的 EverCookie 看起来气场十足,很完美,其实只是理想太美好,显示依旧很残酷——一样的存在诸多缺陷,只是它把一些缺陷不足尽可能降低了而已。

以 canvas指纹 为例:

取代cookie的网站追踪技术:”帆布指纹识别”初探

虽然解决了 cookie 的稳定性——无法删除,但是唯一性、可辨识性并没有解决——重复率太高、ID容易变化:

canvas指纹验证测试报告

这里有个在线指纹测试的例子:

http://jude.me/fingerprint/

5、移动互联网时代下的新挑战

从文初的图上可以看到,在 PC 时代,追踪用户身份技术方案多,也挺靠谱的,但是随着移动互联网大潮的到来,用户逐渐转向了 M 和 APP,形成三大平台三足鼎立的局面,这三大平台的软硬件技术方案各异,比如苹果系列的产品不支持 flash、不允许随便种植 cookie,而 Android 虽然开放,但是开放的尺度太大了,导致了很严重的软硬件碎片化的问题,这给技术方案的通用兼容性带来了严重的问题。应用又分为 NativeAPP 和 webAPP,前者可以很好的和系统结合,拿到系统的硬件信息特征,比如 MAC、IMEI,而 webAPP 大都受限于浏览器隐私策略保护和前端技术限制,没法拿到系统的硬件信息,这就直接导致无法生成一个基于硬件的唯一的、稳定的、准确的“用户ID”,而且想要三端用户身份都打通就成了一个难事,比如:公司三端的用户重合度是 100%,每端 UV 都是一亿,那么三端的总 UV 应该是一亿,但是以现有业界的 cookieID 技术方案来统计 UV,会得出三端总 UV 是三亿的错误结论,而这目前业界也还没有很完善、通用的解决方案。

总结下在移动互联网时代,用户身份识别与追踪的新挑战有两点:

  • 三端用户身份无法打通、统一

  • 追踪识别的成本越来越高,方案越来越复杂化

这或许是商业行为与用户隐私的一场持久博弈,而在这场博弈的背后技术又将会扮演什么角色呢?

6、Refer:

[1] Javascript-Flash-Cookies

https://github.com/nfriedly/Javascript-Flash-Cookies

[2] flash cookie的制作和使用例子详解 一

http://ylq365.iteye.com/blog/1873382

[3] 用户数据跟踪之Flash Cookies

http://www.biaodianfu.com/flash-cookies.html

[4] 使用Flash Cookie技术在客户端永久保存HTTP Cookie

http://www.cnblogs.com/dcba1112/archive/2011/05/05/2037715.html

[5] 不用Cookie的“Cookie”技术:etag

http://blog.jobbole.com/46266/

[6] 网站数据收集

https://support.google.com/partners/answer/6083646?hl=zh-Hans

[7] php 如何对客户端 pc 生成唯一标识?

https://www.v2ex.com/t/133910

[8] 防恶意点击代码系统思路与实现

http://wenku.baidu.com/view/6c0b0749be1e650e52ea9917

[9] Evercookie(永远删不掉的cookie)

http://www.ituring.com.cn/article/35102

[9] 如何设置一个永远无法删除的Cookie

http://www.biaodianfu.com/zombie-cookie.html

[9] 关于浏览器身份追踪技术的研究与整理

http://blog.zsxsoft.com/post/11

[10] evercookie

https://github.com/samyk/evercookie

https://github.com/decli/flask-fingerprint

[11] 取代cookie的网站追踪技术:”帆布指纹识别”初探

http://security.tencent.com/index.php/blog/msg/59

[12] canvas指纹验证测试报告

http://blog.csdn.net/huangm_fat/article/details/38522939

[13] 在线指纹测试例子:

http://jude.me/fingerprint/


相关 [用户 行为 分析] 推荐:

[转载]用户行为分析面面观(之二)

- - 小蚊子乐园
原文地址: 用户行为分析面面观(之二) 作者: 数据小宇军.     上篇博文我们聊了两个问题:用户行为的研究内容和用户的差异性.     如果把用户比作流动的水,那么企业就是蓄水池,新用户从进水管流入,老用户从出水管流出. 企业要灌溉庄稼获取收成,就要有一定的蓄水量,就必须开源节流,开拓新用户的同时,留住老用户.

腾讯开放平台用户数据及行为分析

- - 36氪
在今天腾讯开放平台年会上,腾讯社交平台部总经理Peter表示,“根据腾讯最新一季财报,QQ空间已经有5.5亿活跃用户,QQ有7.2亿活跃用户,朋友网有2亿活跃用户. ”在现场发布的《互联网开放平台白皮书》里,除了 马化腾写给开发者的一封信,腾讯还公布了最新的开放平台数据以及用户行为数据,无论是对于创业者还是开发者,都有很好的参考价值.

简单说明基于日志的用户行为分析

- - 曉生語錄
日志是记录用户操作流的文件,可以用于验证设计、发现问题和挖掘用户需求. 之所以研究用户行为,原因在于:. 1.设计的优劣最终还是需要从用户行为数据中得到反馈. 2.当产品用户达到一定数量级时,可以从用户行为中挖掘需求. 3.设计很多经验来源于用户行为规律,前沿的设计必然要研究用户. 4.“小步快跑”的敏捷开发依赖行为分析,最具说服力.

中国Android用户行为和应用分析

- - cnBeta全文版
北大、伊利诺伊香槟分校、普渡和豌豆荚实验室的研究人员上周在ACM IMC 2015会议上发表了一篇论文《 Characterizing Smartphone Usage Patterns from Millions of Android Users》 (PDF),根据Android第三方应用商店豌豆荚的数据分析了用户应用管理行为和应用网络活动.

推荐系统之用户行为分析

- - IT瘾-dev
基于用户行为的推荐,在学术界名为协同过滤算法. 协同过滤就是指用户可以齐心协力,通过不断地和网站互动,使 自己的推荐列表能够不断过滤掉自己不感兴趣的物品,从而越来越满足自己的需求. 用户行为在个性化推荐系统中一般分两种——显性反馈行为(explicit feedback)和隐性反馈 行为(implicit feedback).

简述常用的用户行为分析模型

- - 人人都是产品经理
​在产品的设计与运营过程中,通过数据对用户行为进行分析,我们可以总结分析出用户行为与产品之间的关联,并针对性地对产品做出改进. 在数据分析的大框架下,通过对用户行为监测获得的数据进行分析研究的行为归结于用户行为分析. 用户行为分析可以让产品更加详细、清楚地了解用户的行为习惯,从而找出网站、app、推广渠道等产品存在的问题,有助于产品发掘高转化率页面,让产品的营销更加精准、有效,提高业务转化率.

如何进行用户行为分析并提高用户粘性

- - 互联网分析
当下,在互联网高速发展的今天,各类产品层出不穷. 从一开始做好一些特定功能满足用户的特定需求,到现在分析用户行为、提高用户体验,我们做了很多也经过了很多,而我们的目的只有一个:让更多的用户使用我们的产品. 用户行为分析、用户粘性,是我们做产品的人最关注的事情,因为这关系到我们的“孩子”最终能够成长成什么样子.

浅谈用户行为分析之用户身份识别:cookie 知多少?

- - leejun_2005的个人页面
对于数据统计分析或者数据挖掘而言,用户是个非常重要的维度,也是统计分析能落地的基础. 一般而言,咱们追踪或者识别一个用户的首选方案是 userID,大多数公司的产品都会要求用户注册、登录操作,都存在一个类似 UMC 的数据库,管理和标示所有的用户. 但这有个前提条件,就是你所在的公司业务必须以闭环为主(比如 qq、微信、淘宝等).

以滴滴出行为例,谈谈如何分析用户评论

- - IT瘾-bigdata
任何2C的产品都避免不了海量的用户评论/反馈,这恐怕对普通用户来说,最直接的向产品表达看法的途径了. 如果能够正确地分析这些评论,发现关键问题,产品就不会走向歪路……不过可不容易. 很多产品对用户评论的重视度并不高,即便愿意花费精力去分析,即便分析了,使用的方法也是五花八门. 我以前实习的时候做过一种“打杂”的工作,就是回复用户反馈.

[原]自学大数据:Hive基于搜狗搜索的用户日志行为分析

- -
”大数据时代“,“大数据/云计算”,“大数据平台”,每天听到太多的大数据相关的词语,好像现在说一句话不跟大数据沾边都不好意思说自己是做IT的. 可能这与整个IT圈子的炒作也有关联,某一个方面来看其实就是一营销术语. 很多朋友就想问,我想做大数据,但是没有这个条件,没有这个数据量,没有那么多业务场景,没有那多集群可以吗.