目录
- 前言
- [一、什么是 Tampermonkey?](#一、什么是 Tampermonkey?)
- [二、Tampermonkey 用户脚本结构](#二、Tampermonkey 用户脚本结构)
- 三、脚本运行时机(重点)
- [四、Tampermonkey 常用 API(GM_*)](#四、Tampermonkey 常用 API(GM_*))
-
- [1、GM_setValue / GM_getValue(持久化存储)](#1、GM_setValue / GM_getValue(持久化存储))
- 2、GM_xmlhttpRequest(跨域网络请求)
- [3、GM_addStyle(动态注入 CSS)](#3、GM_addStyle(动态注入 CSS))
- 4、GM_registerMenuCommand(脚本菜单快捷入口)
- 五、常见开发模式(前端必备)
-
- [1、页面增删改 DOM](#1、页面增删改 DOM)
- [2、向页面注入 UI(按钮/面板)](#2、向页面注入 UI(按钮/面板))
- [3、拦截 AJAX / Fetch(核心)](#3、拦截 AJAX / Fetch(核心))
- 4、注入脚本到页面原生环境(需要时)
- [六、引入外部库(比如 vue / jquery / lodash)](#六、引入外部库(比如 vue / jquery / lodash))
- 七、脚本调试技巧(前端高频)
-
- [1、在浏览器 devtools 使用 console.log](#1、在浏览器 devtools 使用 console.log)
- 2、开启"即时保存"自动刷新
- [3、用 Node/ESLint 写脚本再 copy 进去](#3、用 Node/ESLint 写脚本再 copy 进去)
- 八、常见实战案例(你可以直接扩展)
-
- 1、自动填写表单
- [2、自动翻页 + 自动抓数据](#2、自动翻页 + 自动抓数据)
- 3、修改接口返回内容(黑科技)
- 九、项目级脚本结构(大型脚本)
- 十、开发大型脚本的工程化技巧
- 十一、最佳实践总结(重要)
- [十二、如何防止网站被 Tampermonkey(油猴)脚本穿透攻击?](#十二、如何防止网站被 Tampermonkey(油猴)脚本穿透攻击?)
-
- [1、Tampermonkey 究竟能做什么"攻击"?](#1、Tampermonkey 究竟能做什么“攻击”?)
- 2、前端防御核心目标
- [3、必须做的 10 个前端防御措施(实用,能直接上生产)](#3、必须做的 10 个前端防御措施(实用,能直接上生产))
-
- (1)、重要逻辑全部后端校验
- [(2)、前端的关键参数不要在 DOM 中暴露](#(2)、前端的关键参数不要在 DOM 中暴露)
- [(3)、阻止 Tampermonkey 轻易覆写 fetch / XHR](#(3)、阻止 Tampermonkey 轻易覆写 fetch / XHR)
- (4)、前端使用防篡改技术(Integrity)
- [(5)、关键业务动作需要 CSRF Token(不可通过注入伪造)](#(5)、关键业务动作需要 CSRF Token(不可通过注入伪造))
- (6)、请求参数加签(Sign)
- [(7)、前端不要在 window 暴露任何有价值的数据](#(7)、前端不要在 window 暴露任何有价值的数据)
- [(8)、混淆前端关键逻辑(提高 Tampermonkey 编写成本)](#(8)、混淆前端关键逻辑(提高 Tampermonkey 编写成本))
- [(9)、限制自动化攻击:加入行为验证(Bot Detection)](#(9)、限制自动化攻击:加入行为验证(Bot Detection))
- (10)、前端埋点识别油猴脚本行为
- [3、后端是最终防线(核心原则 ⭐️⭐️⭐️)](#3、后端是最终防线(核心原则 ⭐️⭐️⭐️))
前言
Tampermonkey 开发教程(前端工程师定制版)
一、什么是 Tampermonkey?
Tampermonkey 是一个 浏览器用户脚本管理器,允许你在网页加载后注入 JS/CSS,实现:
- 修改页面内容
- 劫持请求、拦截接口
- 自动化操作(表单填充/自动点击)
- 网页增强功能
- 跨网站数据整合
- 添加快捷键、按钮、UI
你可以把它理解为:
- 一个浏览器里的"本地插件开发框架",但用普通 JS 就能实现。
二、Tampermonkey 用户脚本结构
一个完整脚本:
typescript
// ==UserScript==
// @name Demo Script
// @namespace https://yourdomain.com
// @version 1.0.0
// @description 一个示例油猴脚本
// @match https://www.example.com/*
// @run-at document-end
// @grant GM_xmlhttpRequest
// @grant GM_setValue
// @grant GM_getValue
// ==/UserScript==
(function () {
console.log("脚本已加载");
})();
核心字段说明:
| 字段 | 说明 |
|---|---|
| @match | 匹配网站(最重要) |
| @include / @exclude | 包含 / 排除规则 |
| @run-at | 运行时机(document-start / end / idle 等) |
| @grant | 启用 GM API(跨域、存储等) |
| @require | 引入外部 JS(如 jQuery/Lodash) |
| @resource | 引入外部资源(CSS/JSON 文件等) |
三、脚本运行时机(重点)
| 选项 | 描述 | 用途 |
|---|---|---|
document-start |
DOM 未出现 | 提前注入脚本逻辑、拦截原生 JS |
document-end |
DOM 已可操作 | 常用,页面加载完成后运行 |
document-idle |
更晚一些 | 等待页面渲染完再执行 |
建议前端开发者:
90% 情况 → 用 document-end
四、Tampermonkey 常用 API(GM_*)
Tampermonkey 提供"增强版浏览器能力" API:
- GM_setValue / GM_getValue(持久化存储)
- GM_xmlhttpRequest(跨域网络请求)
- GM_addStyle(动态注入 CSS)
- GM_registerMenuCommand(脚本菜单快捷入口)
1、GM_setValue / GM_getValue(持久化存储)
js
GM_setValue("token", "123456");
const token = GM_getValue("token");
会永久保存,不会被清除。
2、GM_xmlhttpRequest(跨域网络请求)
支持跨域,不受浏览器 CORS 限制。
js
GM_xmlhttpRequest({
method: "GET",
url: "https://api.example.com/data",
onload: res => {
console.log(res.responseText);
}
});
这是最强大能力之一。
3、GM_addStyle(动态注入 CSS)
js
GM_addStyle(`
.my-button {
background: #409eff;
color: white;
}
`);
4、GM_registerMenuCommand(脚本菜单快捷入口)
js
GM_registerMenuCommand("清空缓存", () => {
GM_setValue("token", "");
});
五、常见开发模式(前端必备)
1、页面增删改 DOM
操作 DOM(自动刷新、定时检查):
js
function waitForElement(selector, cb) {
const timer = setInterval(() => {
const el = document.querySelector(selector);
if (el) {
clearInterval(timer);
cb(el);
}
}, 500);
}
waitForElement(".button", el => {
el.click();
});
2、向页面注入 UI(按钮/面板)
js
const btn = document.createElement("button");
btn.innerText = "执行脚本";
btn.style = "position:fixed;top:20px;right:20px;z-index:9999;";
document.body.appendChild(btn);
btn.onclick = () => {
alert("Hello!");
};
3、拦截 AJAX / Fetch(核心)
修改页面原逻辑流程。
拦截 fetch:
js
const rawFetch = unsafeWindow.fetch;
unsafeWindow.fetch = async (...args) => {
console.log("请求参数:", args);
const res = await rawFetch(...args);
return res;
};
4、注入脚本到页面原生环境(需要时)
Tampermonkey 脚本运行在沙箱环境,有时需要共享 window 变量:
typescript
function inject(fn) {
const script = document.createElement("script");
script.textContent = `(${fn})();`;
document.body.appendChild(script);
}
inject(() => {
console.log("代码运行在原生页面环境");
});
拓展:
沙箱:前端沙箱是隔离运行不可信代码以保护主环境的安全执行环境。
前端常见的沙箱实现方式:
- <iframe> 沙箱(最强隔离)
- Web Worker(线程级沙箱)
- 微前端/Widget沙箱(JS执行隔离)
- 在线代码编辑器沙箱
六、引入外部库(比如 vue / jquery / lodash)
在头部加上:
js
// @require https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js
然后直接使用:
js
console.log(_.chunk([1,2,3,4], 2));
尽量使用 CDN
七、脚本调试技巧(前端高频)
1、在浏览器 devtools 使用 console.log
最常用。
2、开启"即时保存"自动刷新
Chrome Tampermonkey 设置 → "保存后立即重新加载脚本"。
3、用 Node/ESLint 写脚本再 copy 进去
适合大型脚本。
八、常见实战案例(你可以直接扩展)
1、自动填写表单
typescript
document.querySelector("#username").value = "test";
document.querySelector("#submit").click();
2、自动翻页 + 自动抓数据
typescript
setInterval(() => {
const next = document.querySelector(".next-button");
if (next) next.click();
}, 2000);
3、修改接口返回内容(黑科技)
typescript
inject(() => {
const open = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function(...args) {
this.addEventListener("load", function() {
if (this.responseURL.includes("target")) {
console.log("返回数据:", this.responseText);
}
});
return open.apply(this, args);
};
});
九、项目级脚本结构(大型脚本)
建议结构:
typescript
my-script/
|- index.user.js // 入口
|- utils/
|- dom.js
|- request.js
|- storage.js
|- modules/
|- auto-login.js
|- ui-panel.js
你可以用 vite/webpack/esbuild 打包,然后输出一个 .user.js。
十、开发大型脚本的工程化技巧
- 用 ESBuild/Vite 新建项目
- 写 ESModule 代码
- 打包成单文件
- 输出 .user.js 文件
- 在 @require 注入你的打包产物
- 可实现 React/Vue UI 面板(脚本级插件 UI)
十一、最佳实践总结(重要)
| 要点 | 说明 |
|---|---|
| 使用 match 精准定位网站 | 避免脚本到处运行 |
| 尽量使用 waitForElement | 页面多为异步加载 |
| 使用 GM API 做存储和跨域 | 避免 localStorage 限制 |
| 复杂逻辑尽量注入原生页面环境 | 防止沙箱隔离 |
| 大型脚本用打包工具工程化 | 可维护性更强 |
十二、如何防止网站被 Tampermonkey(油猴)脚本穿透攻击?
前端无法阻止 Tampermonkey,只能降低攻击表面积;真正的安全必须放在后端。
1、Tampermonkey 究竟能做什么"攻击"?
它可以在你的页面上:
- 修改 DOM(注入按钮、劫持点击事件)
- 注入 JS、覆盖变量、修改全局函数
- 劫持 XMLHttpRequest / fetch
- 修改接口参数、伪造登录信息
- 读取你的页面渲染内容(包括隐藏字段)
- 循环爬数据、自动化机器人行为
- 绕过前端校验逻辑
- 覆盖 window 里的全局变量
- 拦截并伪造前端加密逻辑(如 AES、签名参数)
因此:
你不能从前端阻止油猴,但可以在前后端合力,使攻击者难以"穿透"你的业务逻辑。
2、前端防御核心目标
前端的任务不是"阻止用户注入脚本",而是:
- 让前端的数据 + 行为无法直接影响核心业务,必须经过后端验证。
因此方向是:
- 前端不存放敏感逻辑
- 前端不信任任何来自浏览器的数据
- 把权限、关键校验、业务规则放在后端
- 降低油猴能做的破坏面
3、必须做的 10 个前端防御措施(实用,能直接上生产)
(1)、重要逻辑全部后端校验
不要把这类逻辑写在前端:
- 是否有权限
- 数据是否可操作
- 是否可删除
- 是否可下单
- 是否可访问某个资源
- 价格是否合法
- 库存是否合法
核心:前端永远视为不可信环境。
(2)、前端的关键参数不要在 DOM 中暴露
Tampermonkey 可以轻松读 DOM。
不要把:
- userId
- token
- role
- 权限字
- 数据签
- config.js 中的敏感开关
- 放到 DOM 或 window 全局变量。
解决:放在 HttpOnly Cookie 或后端生成服务端 session。
(3)、阻止 Tampermonkey 轻易覆写 fetch / XHR
Tampermonkey 常用攻击手段:劫持 fetch 实现自动化攻击。
你可以:
- 加固 fetch(不可完全阻止,但可增加代价)
js
const rawFetch = window.fetch;
Object.defineProperty(window, "fetch", {
get() { return rawFetch; },
set() { console.warn("fetch override blocked"); }
});
攻击者仍能覆盖,但成本高很多,需要注入到 <script> 环境且更精细。
(4)、前端使用防篡改技术(Integrity)
对引入的脚本加 SRI:
html
<script src="/app.js" integrity="sha384-xxx" crossorigin="anonymous"></script>
Tampermonkey 注入脚本无法替换你的资源文件。
(5)、关键业务动作需要 CSRF Token(不可通过注入伪造)
- 通过后端生成随机 token + HttpOnly + SameSite 再配合 header 验证。
- 油猴脚本不能读取 HttpOnly cookie。
(6)、请求参数加签(Sign)
在客户端加密/签名 → 没意义:Tampermonkey 可直接读取你 JS 里的加密代码、密钥、算法。
正确做法:后端使用私钥签名,前端无法伪造。
比如:
- 每个操作有 server-side nonce
- 参数签名由后端返回前端,不在 JS 中写任何私钥
- 所有关键操作必须携带服务端生成的签名
(7)、前端不要在 window 暴露任何有价值的数据
Tampermonkey 最喜欢这样:
typescript
window.user = { role: "admin" }
油猴脚本可以直接修改:
typescript
unsafeWindow.user.role = "admin";
正确做法:
- 不暴露全局变量
- 使用闭包 / 模块化
- 使用 ShadowRealm(如果可用)
- 使用 Proxy 包装全局对象
(8)、混淆前端关键逻辑(提高 Tampermonkey 编写成本)
不能提供完全安全,但能让攻击者代价提高 10 倍以上。
工具推荐:
- javascript-obfuscator(混淆)
- rollup/webpack scope hoisting(减少暴露)
- Terser mangling(变量名压缩)
- Tampermonkey 最怕阅读晦涩难懂的混淆代码。
(9)、限制自动化攻击:加入行为验证(Bot Detection)
油猴脚本喜欢自动化执行:
- 自动下单
- 高频请求
- 爬虫
你可以加入:
- 行为风控
- 是否频繁点击
- 是否没有鼠标轨迹
- 是否没有滚动事件
- 定时任务频率
- 同 IP 请求速率
- 前端收集 → 后端识别。
(10)、前端埋点识别油猴脚本行为
油猴脚本往往有行为特征:
- 非真实点击事件(click())
- 非真实输入(element.value=xxx)
- 短时间反复请求 API
- 特定 UA 特征(有的油猴脚本会改 UA)
- 埋点检测可在后端限制可疑行为。
3、后端是最终防线(核心原则 ⭐️⭐️⭐️)
最终只能靠后端保证安全。
后端必须做:
| 防线 | 目的 |
|---|---|
| 服务端权限校验 | 前端身份不可信 |
| 服务端参数合法性检查 | 价格、ID、角色不可伪造 |
| 服务端日志审计 | 识别异常操作 |
| 限频 | 阻止自动化脚本 |
| CSRF | 防止跨站攻击 |
| 服务端签名 | 前端永远不要有私钥 |