🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

那是個平靜的下午。

我正在掘金上摸魚寫文章,程式碼編輯器在另一個螢幕上裝模作樣地躺著。

突然,一個熟悉的聲音從身後傳來:

"小明,在幹嘛呢?"

心跳瞬間飆到 180,腎上腺素狂飆。我的手指以肌肉記憶般的速度按下了 Alt+Q

0.1 秒後——

螢幕上的掘金文章瞬間蒸發,取而代之的是一個樸實無華的百度首頁。

我淡定轉身,面不改色: "老闆,正準備查個技術問題!"

老闆滿意地点頭,拍了拍我的肩膀:"不錯,要多鑽研。" 然後轉身離開。

我長舒一口氣,心率逐漸平復。再次按下 Alt+Q——掘金文章完美回到原位。

這不是科幻片,也不是魔術。

這是我上週剛寫出來的 瀏覽器偽裝插件 —— 一個真正的"職場求生神器"。

今天,我就把這個插件製作過程,毫無保留地分享給你。

先看效果:按下 Alt+Q顯示百度界面,再次按下 Alt+Q回到原來頁面

摸魚插件效果.gif

需求分析

核心功能

  • 一鍵切換:按快捷鍵(Alt+Q)0.1秒瞬間切換
  • 完美偽裝:標題、圖標、頁面內容三位一體
  • 無縫恢復:再按一次,一切如初
  • 兼容性強:支持99%的网站(包括掘金、知乎、B站...)

立即使用

5分鐘搞定安裝:複製程式碼 → 創建文件 → 載入擴展 → 開始使用!

📦 獲取完整程式碼 👉 GitHub: https://github.com/Teernage/disguise-extension/tree/main 如果對你有幫助,歡迎 Star ⭐ 支持!

實現過程

第一步:創建插件結構

disguise-extension/
├── manifest.json      # 插件配置文件
├── background.js      # 後台腳本
├── disguise.js        # 核心邏輯
└── rules.json         # 網路請求規則

第二步:配置 manifest.json

{
  "manifest_version": 3,
  "name": "網站偽裝器",
  "version": "1.0",
  "permissions": ["activeTab", "scripting", "declarativeNetRequest"],
  "host_permissions": ["<all_urls>"],
  "background": {
    "service_worker": "background.js"
  },
  "content_scripts": [
    {
      "matches": ["<all_urls>"],
      "js": ["disguise.js"]
    }
  ],
  "declarative_net_request": {
    "rule_resources": [
      {
        "id": "remove_frame_headers",
        "enabled": true,
        "path": "rules.json"
      }
    ]
  },
  "commands": {
    "toggle": {
      "suggested_key": { "default": "Alt+Q" },
      "description": "切換偽裝"
    }
  }
}

關鍵配置說明:

  • permissions:申請必要權限
  • content_scripts:在所有網頁注入腳本
  • declarativeNetRequest:修改 HTTP 響應頭
  • commands:註冊快捷鍵

第三步:處理快捷鍵(background.js)

// 監聽快捷鍵
chrome.commands.onCommand.addListener(async (command) => {
  if (command === 'toggle') {
    const [tab] = await chrome.tabs.query({
      active: true,
      currentWindow: true,
    });
    chrome.tabs.sendMessage(tab.id, { action: 'toggle' });
  }
});

工作流程:

用戶按 Alt+Q
    ↓
background.js 監聽到快捷鍵
    ↓
發送消息到當前標籤頁
    ↓
disguise.js 接收消息並執行切換

第四步:核心偽裝邏輯(disguise.js)

const config = {
  url: 'https://www.baidu.com/',
  title: '百度一下',
};

let isDisguised = false;
let originalTitle = document.title;
let originalIcon = null;

// 接收快捷鍵消息
chrome.runtime.onMessage.addListener((msg) => {
  if (msg.action === 'toggle') {
    toggle();
  }
});

function toggle() {
  isDisguised = !isDisguised;
  let iframe = document.getElementById('work-iframe');

  if (isDisguised) {
    // 保存原始圖標
    const iconLink = document.querySelector('link[rel*="icon"]');
    if (iconLink) originalIcon = iconLink.href;

    // 修改標題和圖標
    document.title = config.title;
    changeFavicon(`${config.url}/favicon.ico`);

    // 創建或顯示 iframe
    if (!iframe) {
      iframe = document.createElement('iframe');
      iframe.id = 'work-iframe';
      iframe.src = config.url;

      // 設置iframe樣式
      Object.assign(iframe.style, {
        position: 'fixed',
        top: '0',
        left: '0',
        width: '100vw',
        height: '100vh',
        zIndex: '2147483647',
        border: 'none',
        background: 'white',
      });

      // 添加加載錯誤處理
      iframe.onerror = () => {
        console.warn('iframe 加載失敗,可能被跨域阻止');
        showFallbackMessage(iframe);
      };

      document.body.appendChild(iframe);
    }
    iframe.style.display = 'block';
  } else if (iframe) {
    // 恢復原始標題和圖標
    document.title = originalTitle;
    if (originalIcon) {
      changeFavicon(originalIcon);
    } else {
      // 如果沒有原始圖標,移除當前圖標
      const currentIcon = document.querySelector('link[rel*="icon"]');
      if (currentIcon) currentIcon.remove();
    }

    iframe.style.display = 'none';
  }
}

function changeFavicon(iconUrl) {
  // 移除所有現有的圖標鏈接
  const existingIcons = document.querySelectorAll('link[rel*="icon"]');
  existingIcons.forEach((icon) => icon.remove());

  // 創建新的圖標鏈接
  const link = document.createElement('link');
  link.rel = 'icon';
  link.type = 'image/x-icon';
  link.href = iconUrl;
  document.head.appendChild(link);
}

// 當 iframe 被阻止時顯示 404 頁面
function showFallbackMessage(iframe) {
  const fallback = document.createElement('div');
  fallback.id = 'fallback-message';
  fallback.innerHTML = `
    <div style="
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100vh;
      background: #f5f5f5;
      font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
      margin: 0;
      color: #333;
    ">
      <div style="text-align: center; max-width: 600px; padding: 40px;">
        <h1 style="
          font-size: 120px;
          margin: 0;
          color: #ddd;
          font-weight: 700;
        ">404</h1>
        <h2 style="
          font-size: 24px;
          margin: 20px 0;
          color: #666;
          font-weight: 400;
        ">頁面未找到</h2>
        <p style="
          font-size: 16px;
          color: #999;
          line-height: 1.6;
          margin: 20px 0;
        ">
          抱歉,您訪問的頁面不存在或已被刪除。
        </p>
        <div style="margin-top: 30px;">
          <a href="${config.url}" style="
            display: inline-block;
            padding: 12px 30px;
            background: #1a73e8;
            color: white;
            text-decoration: none;
            border-radius: 4px;
            font-size: 14px;
            transition: background 0.3s;
          " onmouseover="this.style.background='#1557b0'" 
             onmouseout="this.style.background='#1a73e8'">
            返回首頁
          </a>
        </div>
      </div>
    </div>`;
  iframe.style.display = 'none';
  document.body.appendChild(fallback);
}

第五步 rules.json

很多網站(如百度)設置了 X-Frame-Options 響應頭,禁止被 iframe 嵌入。

我們需要通過 declarativeNetRequest 移除這些限制:

[
  {
    "id": 1,
    "priority": 1,
    "action": {
      "type": "modifyHeaders",
      "responseHeaders": [
        {
          "header": "X-Frame-Options",
          "operation": "remove"
        },
        {
          "header": "Content-Security-Policy",
          "operation": "remove"
        }
      ]
    },
    "condition": {
      "urlFilter": "*",
      "resourceTypes": ["sub_frame"]
    }
  }
]

作用:

  • 移除 X-Frame-Options 響應頭
  • 移除 Content-Security-Policy 響應頭
  • 允許任何網站被 iframe 嵌入

技術細節

1. 為什麼用 iframe?

方案對比:

方案 優點 缺點
修改 DOM 簡單 無法完美還原複雜網站
截圖替換 逼真 無法交互
iframe 嵌入 完美偽裝 + 可交互 可能被跨域阻止

最終選擇: iframe + 跨域繞過

2. 如何處理跨域限制?

問題:

很多網站設置了 X-Frame-Options: DENY,禁止被 iframe 嵌入。

解決方案:

使用 Chrome 擴展的 declarativeNetRequest API,在響應到達瀏覽器前移除這些響應頭。

{
  "action": {
    "type": "modifyHeaders",
    "responseHeaders": [{ "header": "X-Frame-Options", "operation": "remove" }]
  }
}

原理:

伺服器返回響應
    ↓
X-Frame-Options: DENY
    ↓
插件攔截並移除響應頭
    ↓
瀏覽器接收到無限制的響應
    ↓
iframe 成功加載 ✅

安裝使用

安裝:開發者模式加載

  1. 打開 Chrome 瀏覽器
  2. 訪問 chrome://extensions/
  3. 開啟「開發者模式」
  4. 點擊「加載已解壓的擴展程序」
  5. 選擇 disguise-extension 文件夾

安裝摸魚插件.gif

用法

  1. 訪問任意網站(如掘金)
  2. 按 Alt+Q
  3. 頁面瞬間變成百度首頁
  4. 再按 Alt+Q 恢復

自定義偽裝網站

修改 disguise.js 中的配置:

const config = {
  url: 'https://www.baidu.com/',     // 偽裝的網站
  title: '百度一下',                  // 標籤頁標題
};

重要提醒: 此插件僅供學習交流,請勿在工作時間摸魚!🤣
如果覺得對您有幫助,歡迎點讚 👍 收藏 ⭐ 关注 🔔 支持一下!


原文出處:https://juejin.cn/post/7568055953310662707


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝17   💬4   ❤️6
547
🥈
我愛JS
📝1   💬4   ❤️2
47
🥉
酷豪
1
#5
1
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付