无限进步:浅谈Vue反爬技术

41 阅读5分钟

前不久玩了一下n8n,并利用n8n的HttpRequest做了很多有意思的项目,例如遇到一些会对浏览器进行Header检查时,添加相关的浏览器标识,就可以通过检查进而爬取数据。

但如果遇到像Vue等需要我们的浏览器开启JavaScript支持后才可以访问的网站没有办法,就在尝试一筹莫展时,高级爬虫Selenium、Puppeteer 等无头浏览器为我解决了这个问题,这让我不禁想到——“没有绝对的防御”。

这些项目中遇到的难题,也成了我宝贵的学习经验,反过来思考自己的网站项目,是否也可以对网站的安全防护进行进一步的提升,来应对大部分的简单爬虫。

由于我大部分做的是Vue项目,这次就来聊一聊Vue项目的防御:

一、代码混淆

这是最直接最简单的一个防御技巧,为的是防止爬虫开发这直接查看你网站的加密算法、API签名逻辑,从而逆向破解你的信息传输,就像间谍取得了暗号,这样他就可以伪造你做任何事情。

在Vue项目中,我们可以这么做:

  • 关闭 SourceMap: 如果使用Vite来打包网站,默认是自动关闭SourceMap,关闭后就没有办法让浏览器还原我们的Vue代码(之前苹果应用商店因为不小心打开了SouceMap,造成了源地址的泄露,现在我们可以直接在网页上访问苹果应用商店了)

image.png 关闭SourceMap很简单,只需在vue.config.js中配置,禁止生成sourceMap文件即可:

// vue.config.js
module.exports = {
  productionSourceMap: false,
}
  • 代码混淆: 利用代码混淆工具,可以把变量名变成 _0x5d2f 这样的乱码字符,并打乱控制流,让逆向工程极其痛苦。

    常见的混淆工具:

    • Webpack: webpack-obfuscator
    • Vite: rollup-plugin-obfuscator

    Vue项目中Vite以及Webpack代码混淆处理

二、强制关闭Debugger模式

你想爬取我的网站,那不好意思,我狠起来连自己都打!直接不让用户打开DevTools,防止爬虫开发者打开控制台分析网站接口和 DOM 结构。在这里有两种操作方式:

  • 无限Debugger陷阱: 只需要在 Vue 的 main.js 中加入一段代码,一旦检测到控制台打开,就会不断触发 debugger 断点(之前想看美团的代码,结果把我卡死了!我很确信它们就是做了陷阱。),卡死爬取者的浏览器。不过这种方式也有解决办法,只是操作难度稍微有点高。

    今天彻底解决无限debugger问题

    // 简易版
    setInterval(function() {
        check();
    }, 2000);
    var check = function() {
        function doCheck(a) {
            if (("" + a/a)["length"] !== 1 || a % 20 === 0) {
                (function() {}
                ["constructor"]("debugger")())
            } else {
                (function() {}
                ["constructor"]("debugger")())
            }
            doCheck(++a)
        }
        try {
            doCheck(0)
        } catch (err) {}
    };
    
  • 禁用右键和F12按键: 能挡住大部分的新手爬虫开发者

    document.oncontextmenu = () => false; // 禁右键
    document.onkeydown = (e) => {
        if (e.keyCode === 123) return false; // 禁F12
        if (e.ctrlKey && e.shiftKey && e.keyCode === 'I'.charCodeAt(0)) return false; // 禁Ctrl+Shift+I
    };
    

三、数据层面——数据传输防御

我觉得这才是数据爬取最害怕的事情,爬取到了数据,但是数据加密了读不懂。

  • 字体混淆: 这是美团、大众点评、猫眼电影最常用的手段。爬虫抓下来的 HTML 是乱码,必须解析字体文件才能还原,成本极高。

    Gemini_Generated_Image_7yl42x7yl42x7yl4.png

    因为字体混淆的操作难度较高,且大部分网站防护都不需要这么严密,具体操作可以看这篇链接:

    【小记】探探学习平台的字体混淆

  • CSS 伪元素内容: 重要数据不写在 HTML 标签里,而是写在 CSS 的 content 属性中。

     .price::before {
         content: "¥99.00"; /* 爬虫如果不解析 CSS 是拿不到这个值的 */
     }
    
  • 动态 Class 类名: 利用 Vue 的 CSS Modules,让类名变成随机哈希值(如 .style_price_x7z9)。这会让依赖 css选择器的爬虫失效,因为类名每次打包甚至每次刷新都可能变。

四、通信安全—— 针对接口抓取

既然页面难爬,很多人会选择直接抓 API。所以需要我们在接口请求上做一些手脚。

  • API 签名/JWT签发:

    前端在发送请求时,利用密钥(混淆在前端代码中)+ 时间戳 + 请求参数,计算一个 Hash 值放在 Header 里。后端校验这个 Hash(数据被篡改,hash值会被修改,因此无法验证)。如果爬虫只是重放请求或篡改参数,后端会直接拒绝。

Gemini_Generated_Image_t9iyett9iyett9iy.png

  • 数据加密:

    后端返回的数据不是明文 JSON,而是加密字符串Base64AES。前端收到后解密再渲染。这能有效防止直接通过 Network 面板抓包获取数据。

五、行为验证 (针对自动化工具)

针对 SeleniumPuppeteer 等高级爬虫要做一些特殊处理,这类爬虫我有尝试过,它是使用一个真实存在的浏览器来发起请求,所以单纯检查JS是否开启、Header头文件都没有作用了,好在,它们仍然是存在一些特征,能让我们进行识别:

  • Canvas 指纹:

    在页面加载时,用 Canvas 绘制一段隐藏的图形。不同浏览器、不同硬件渲染出来的像素略有差异。如果是标准的无头浏览器环境,大部分爬虫都是在linux等没有显卡的服务器运行,指纹特征会十分明显,可以直接封禁。

  • 安全验证码:

    在关键操作(登录、查询)前引入滑动拼图、人机验证。现在有很多 Vue 的插件(如 vue3-puzzle-vcode。除此之外我还选择使用Cloudflare TurnStile做人机验证,后续我也会写一篇教程专门讲如何接入Cloudflare TurnStile。

六、最后

对于 Vue 项目,效果较好的组合是:打包混淆API签名或做安全验证,如果要保护的数据价值极高(像美团的数据),那么字体混淆是必修课。网站的攻防是一门很意思的课程,但是一定记住 “没有绝对的防御” ,我们可以在不断的学习中,不断提高自己的知识储备,耐心学习新的支持,这样才能与时俱进,无限进步!