前不久玩了一下n8n,并利用n8n的HttpRequest做了很多有意思的项目,例如遇到一些会对浏览器进行Header检查时,添加相关的浏览器标识,就可以通过检查进而爬取数据。
但如果遇到像Vue等需要我们的浏览器开启JavaScript支持后才可以访问的网站没有办法,就在尝试一筹莫展时,高级爬虫Selenium、Puppeteer 等无头浏览器为我解决了这个问题,这让我不禁想到——“没有绝对的防御”。
这些项目中遇到的难题,也成了我宝贵的学习经验,反过来思考自己的网站项目,是否也可以对网站的安全防护进行进一步的提升,来应对大部分的简单爬虫。
由于我大部分做的是Vue项目,这次就来聊一聊Vue项目的防御:
一、代码混淆
这是最直接最简单的一个防御技巧,为的是防止爬虫开发这直接查看你网站的加密算法、API签名逻辑,从而逆向破解你的信息传输,就像间谍取得了暗号,这样他就可以伪造你做任何事情。
在Vue项目中,我们可以这么做:
- 关闭 SourceMap: 如果使用Vite来打包网站,默认是自动关闭SourceMap,关闭后就没有办法让浏览器还原我们的Vue代码(之前苹果应用商店因为不小心打开了SouceMap,造成了源地址的泄露,现在我们可以直接在网页上访问苹果应用商店了)
关闭SourceMap很简单,只需在
vue.config.js中配置,禁止生成sourceMap文件即可:
// vue.config.js
module.exports = {
productionSourceMap: false,
}
-
代码混淆: 利用代码混淆工具,可以把变量名变成
_0x5d2f这样的乱码字符,并打乱控制流,让逆向工程极其痛苦。常见的混淆工具:
- Webpack:
webpack-obfuscator - Vite:
rollup-plugin-obfuscator
- Webpack:
二、强制关闭Debugger模式
你想爬取我的网站,那不好意思,我狠起来连自己都打!直接不让用户打开DevTools,防止爬虫开发者打开控制台分析网站接口和 DOM 结构。在这里有两种操作方式:
-
无限Debugger陷阱: 只需要在 Vue 的 main.js 中加入一段代码,一旦检测到控制台打开,就会不断触发 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 是乱码,必须解析字体文件才能还原,成本极高。
因为字体混淆的操作难度较高,且大部分网站防护都不需要这么严密,具体操作可以看这篇链接:
-
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值会被修改,因此无法验证)。如果爬虫只是重放请求或篡改参数,后端会直接拒绝。
-
数据加密:
后端返回的数据不是
明文 JSON,而是加密字符串Base64或AES。前端收到后解密再渲染。这能有效防止直接通过 Network 面板抓包获取数据。
五、行为验证 (针对自动化工具)
针对 Selenium、Puppeteer 等高级爬虫要做一些特殊处理,这类爬虫我有尝试过,它是使用一个真实存在的浏览器来发起请求,所以单纯检查JS是否开启、Header头文件都没有作用了,好在,它们仍然是存在一些特征,能让我们进行识别:
-
Canvas 指纹:
在页面加载时,用 Canvas 绘制一段隐藏的图形。不同浏览器、不同硬件渲染出来的像素略有差异。如果是标准的无头浏览器环境,大部分爬虫都是在linux等没有显卡的服务器运行,指纹特征会十分明显,可以直接封禁。
-
安全验证码:
在关键操作(登录、查询)前引入滑动拼图、人机验证。现在有很多 Vue 的插件(如 vue3-puzzle-vcode。除此之外我还选择使用Cloudflare TurnStile做人机验证,后续我也会写一篇教程专门讲如何接入Cloudflare TurnStile。
六、最后
对于 Vue 项目,效果较好的组合是:打包混淆 、API签名或做安全验证,如果要保护的数据价值极高(像美团的数据),那么字体混淆是必修课。网站的攻防是一门很意思的课程,但是一定记住 “没有绝对的防御” ,我们可以在不断的学习中,不断提高自己的知识储备,耐心学习新的支持,这样才能与时俱进,无限进步!