数据抓取拦截javascript设置的cookie

1 背景

在进行数据抓取时,找javascript生成的cookie通常是一件很烦人的事情。如果能一步定位到cookie是哪个javascript文件生成,那么会极大减轻工作量。

2 原理

我们设置cookie会通过document.cookie来设置。当设置cookie时,能触发我们增加的拦截功能即可。

如果一个对象具有一个属性,我们可以获取该对象的属性描述符,并覆盖属性描述符对象的set方法来完成拦截功能。

属性描述符是ES5中新增的概念,其作用是给对象的属性增加更多的控制。当通过document.cookie设置修改属性时,属性描述符的set方法会被调用。

而我们只需要重写这个方法,当document.cookie发生时,先调我们设置的拦截操作,最终再调document.cookie即可实现。具体实现涉及到了属性拦截涉及了属性描述符、原型对象、及闭包概念。可查看参考资料[1]学习。

为了给浏览器增加这个功能,我们将能够拦截cookie设置的js脚本通过编写chrome插件,在页面文档加载前注入页面中。随后页面有cookie设置动作发生时,拦截会被触发。

3 实现分析

chrome插件体系结构概述中介绍的content script就是我们要这里编写的拦截脚本。拦截脚本实现如下。代码取自[2]。

function breakOn(obj, propertyName, mode, func) {
    function getPropertyDescriptor(obj, name) {
        var property = Object.getOwnPropertyDescriptor(obj, name);
        var proto = Object.getPrototypeOf(obj);
        while (property === undefined && proto !== null) {
            property = Object.getOwnPropertyDescriptor(proto, name);
            proto = Object.getPrototypeOf(proto);
        }
        return property;
    }

    function verifyNotWritable() {
        if (mode !== 'read')
            throw "This property is not writable, so only possible mode is 'read'.";
    }

    var enabled = true;
    var originalProperty = getPropertyDescriptor(obj, propertyName);
    var newProperty = { enumerable: originalProperty.enumerable };

    // write
    if (originalProperty.set) {// accessor property
        newProperty.set = function(val) {
            if(enabled && (!func || func && func(val)))
                debugger;
            
            originalProperty.set.call(this, val);
        }
    } else if (originalProperty.writable) {// value property
        newProperty.set = function(val) {
            if(enabled && (!func || func && func(val)))
                debugger;

            originalProperty.value = val;
        }
    } else  {
        verifyNotWritable();
    }

    // read
    newProperty.get = function(val) {
          if(enabled && mode === 'read' && (!func || func && func(val)))
            debugger;

        return originalProperty.get ? originalProperty.get.call(this, val) : originalProperty.value;
    }

    Object.defineProperty(obj, propertyName, newProperty);

    return {
      disable: function() {
        enabled = false;
      },

      enable: function() {
        enabled = true;
      }
    };
};

4 参考

[1]javascript基础知识,https://wangdoc.com/javascript/oop/prototype.html

[2]属性拦截,https://github.com/paulirish/break-on-access/blob/master/break-on-access.js

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值