那是個平靜的下午。
我正在掘金上摸魚寫文章,程式碼編輯器在另一個螢幕上裝模作樣地躺著。
突然,一個熟悉的聲音從身後傳來:
"小明,在幹嘛呢?"
心跳瞬間飆到 180,腎上腺素狂飆。我的手指以肌肉記憶般的速度按下了 Alt+Q。
0.1 秒後——
螢幕上的掘金文章瞬間蒸發,取而代之的是一個樸實無華的百度首頁。
我淡定轉身,面不改色: "老闆,正準備查個技術問題!"
老闆滿意地点頭,拍了拍我的肩膀:"不錯,要多鑽研。" 然後轉身離開。
我長舒一口氣,心率逐漸平復。再次按下 Alt+Q——掘金文章完美回到原位。
這不是科幻片,也不是魔術。
這是我上週剛寫出來的 瀏覽器偽裝插件 —— 一個真正的"職場求生神器"。
今天,我就把這個插件製作過程,毫無保留地分享給你。
Alt+Q顯示百度界面,再次按下 Alt+Q回到原來頁面5分鐘搞定安裝:複製程式碼 → 創建文件 → 載入擴展 → 開始使用!
disguise-extension/
├── manifest.json # 插件配置文件
├── background.js # 後台腳本
├── disguise.js # 核心邏輯
└── rules.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:註冊快捷鍵// 監聽快捷鍵
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 接收消息並執行切換
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);
}
很多網站(如百度)設置了 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 響應頭方案對比:
| 方案 | 優點 | 缺點 |
|---|---|---|
| 修改 DOM | 簡單 | 無法完美還原複雜網站 |
| 截圖替換 | 逼真 | 無法交互 |
| iframe 嵌入 | 完美偽裝 + 可交互 | 可能被跨域阻止 |
最終選擇: iframe + 跨域繞過
很多網站設置了 X-Frame-Options: DENY,禁止被 iframe 嵌入。
使用 Chrome 擴展的 declarativeNetRequest API,在響應到達瀏覽器前移除這些響應頭。
{
"action": {
"type": "modifyHeaders",
"responseHeaders": [{ "header": "X-Frame-Options", "operation": "remove" }]
}
}
原理:
伺服器返回響應
↓
X-Frame-Options: DENY
↓
插件攔截並移除響應頭
↓
瀏覽器接收到無限制的響應
↓
iframe 成功加載 ✅
chrome://extensions/disguise-extension 文件夾修改 disguise.js 中的配置:
const config = {
url: 'https://www.baidu.com/', // 偽裝的網站
title: '百度一下', // 標籤頁標題
};
重要提醒: 此插件僅供學習交流,請勿在工作時間摸魚!🤣
如果覺得對您有幫助,歡迎點讚 👍 收藏 ⭐ 关注 🔔 支持一下!