油猴(Tampermonkey)开发“攻防一体化”

目录

前言

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 防止跨站攻击
服务端签名 前端永远不要有私钥
相关推荐
深蓝电商API20 天前
“油猴”脚本变身爬虫:Tampermonkey辅助自动化与数据采集
爬虫·自动化·tampermonkey
soldier_jw1 年前
油猴支持阿里云自动登陆插件
阿里云·云计算·油猴
自由奔跑的小虎1 年前
Edge浏览器油猴插件的安装与使用
edge·油猴
「江太白」2 年前
【ChatGPT with Date】使用 ChatGPT 时显示消息时间的插件
chatgpt·插件·tampermonkey
悟道子HD2 年前
edge浏览器常见问题(技巧)总结
经验分享·ai·edge·浏览器·插件·油猴·新必应
孤独的东北虎2 年前
如何下载知网论文、专利的PDF格式
pdf·插件·油猴·知网·caj·pdf批量下载
微齐天大圣.2 年前
浏览器添加油猴(tampermonkey)扩展
油猴·tampermonkey