debugger阻止反调试(阻止打开控制台)

debugger阻止打开控制台

一、为什么需要反调试?

浏览器开发者工具是前端开发的得力助手,但同时也为"不速之客"提供了便利。通过控制台,攻击者可以:

  • 动态修改变量、调用函数,绕过前端校验

  • 窃取 API 请求参数与响应数据

  • 复制敏感 DOM 结构或业务逻辑

  • 无限调试,分析代码执行流程

  • 虽然无法做到绝对安全,但通过增加调试门槛,可以大幅提升攻击成本,让大多数脚本小子知难而退。

二、整体设计思路

我们设计的反调试模块需满足以下目标:

  • 无感知集成:与 Vue 应用生命周期无缝衔接,仅在 production 环境启用。

  • 多重检测:结合窗口尺寸差异、元素偏移、定时器等多种手段,提高检测准确率。

  • 主动防御:检测到调试后,立即锁屏并注入高频 debugger 指令,干扰调试器执行。

  • 延迟挂载:若页面加载时控制台已打开,则暂缓 Vue 应用挂载,防止应用代码被提前断点。

  • 资源清理:提供销毁方法,便于组件卸载时释放监听器与定时器。

三、入口集成:条件启用 + 防重复挂载

mian.js

js 复制代码
// main.js
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';
import Antd from 'ant-design-vue/es';
import 'ant-design-vue/dist/antd.less';
import { initAntiDebugProtection } from './utils/antiDebug';


/**
 * 挂载 Vue 应用的函数(避免重复挂载)
 */
let appInstance = null;


function mountApp() {

 // 防止重复挂载
  if (appInstance) return;
  appInstance = createApp(App);
  appInstance.use(router);
  appInstance.use(Antd);
  appInstance.mount('#app');
  console.log('✅ Vue 应用已挂载');
}



// 仅生产环境启用反调试,开发环境直接挂载
if (process.env.NODE_ENV === 'production') {
  initAntiDebugProtection(mountApp);
} else {
  mountApp();
}

关键点解析:

  • appInstance 单例模式防止热更新时重复挂载。

  • 通过 process.env.NODE_ENV 区分环境,开发时避免干扰正常调试。

  • 将 mountApp 作为回调传入反调试模块,由模块决定何时真正挂载(若控制台关闭则立即挂载,否则等待关闭)。

四、反调试核心实现

antiDebug.js

js 复制代码
/**
 * 反调试保护模块
 * 功能:屏蔽快捷键、检测开发者工具、高频 debugger 干扰、延迟挂载
 * 使用:在生产环境调用 initAntiDebugProtection(mountCallback)
 */

let initialized = false;          // 防止重复初始化
let debuggerInterval = null;      // debugger 定时器句柄
let isOpen = false;              // 控制台是否打开
let mountCallback = null;        // 挂载回调函数
let isMounted = false;           // 是否已完成挂载

/**
 * 初始化反调试保护
 * @param {Function} onMountReady - 当控制台关闭时执行的回调(通常用于挂载 Vue 应用)
 * @returns {Function} destroy - 销毁清理函数
 */
export function initAntiDebugProtection(onMountReady) {
  // 1. 防止重复初始化
  if (initialized) {
    console.warn('[antiDebug] Already initialized');
    return;
  }

  // 2. SSR 兼容:服务端直接返回
  if (typeof window === 'undefined' || typeof document === 'undefined') {
    return;
  }

  // 3. 等待 DOM 就绪
  if (!document.body) {
    window.addEventListener(
      'DOMContentLoaded',
      () => {
        initAntiDebugProtection(onMountReady);
      },
      { once: true }
    );
    return;
  }

  initialized = true;
  mountCallback = onMountReady || (() => {});

  // ---------- 4. 屏蔽快捷键 / 右键 ----------
  document.addEventListener('contextmenu', (e) => e.preventDefault());
  document.addEventListener('keydown', (e) => {
    if (
      e.key === 'F12' ||
      (e.ctrlKey && e.shiftKey && (e.key === 'I' || e.key === 'J')) ||
      (e.ctrlKey && e.key === 'u')
    ) {
      e.preventDefault();
      return false;
    }
  });

  // ---------- 5. 创建遮罩层 ----------
  const overlay = document.createElement('div');
  overlay.id = '__anti_debug_overlay';
  overlay.style.cssText = `
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.85);
    color: white;
    font-size: 24px;
    display: none;
    justify-content: center;
    align-items: center;
    z-index: 99999;
    pointer-events: none;
    user-select: none;
    font-family: sans-serif;
  `;
  overlay.textContent = '⚠️ 检测到调试工具,页面已锁定';
  document.body.appendChild(overlay);

  // ---------- 6. 创建隐藏检测元素 ----------
  const detector = document.createElement('div');
  detector.id = '__anti_debug_detector';
  detector.style.cssText = `
    position: fixed;
    bottom: 0;
    right: 0;
    width: 100px;
    height: 100px;
    z-index: -9999;
    opacity: 0;
    pointer-events: none;
  `;
  document.body.appendChild(detector);

  // ---------- 7. 核心检测函数 ----------
  function checkDevTools() {
    // 策略1:窗口尺寸差异检测(停靠模式)
    const widthDiff = window.outerWidth - window.innerWidth;
    const heightDiff = window.outerHeight - window.innerHeight;
    const threshold = 150;

    // 策略2:隐藏元素偏移检测(弹出模式)
    const rect = detector.getBoundingClientRect();
    const elementMoved =
      rect.left < 0 ||
      rect.top < 0 ||
      rect.width !== 100 ||
      rect.height !== 100;

    const detected =
      widthDiff > threshold || heightDiff > threshold || elementMoved;

    if (detected) {
      // --- 控制台打开 ---
      if (!isOpen) {
        isOpen = true;
        overlay.style.display = 'flex';

        // 立即执行一次 debugger(同步)
        (function () {})['constructor']('debugger')();

        // 启动高频 debugger 循环(每 10ms 打断)
        if (!debuggerInterval) {
          debuggerInterval = setInterval(() => {
            (function () {})['constructor']('debugger')();
          }, 10);
        }
      }
    } else {
      // --- 控制台关闭 ---
      if (isOpen) {
        isOpen = false;
        overlay.style.display = 'none';

        // 停止 debugger 循环
        if (debuggerInterval) {
          clearInterval(debuggerInterval);
          debuggerInterval = null;
        }

        // 执行挂载回调(如果尚未挂载)
        if (!isMounted) {
          isMounted = true;
          mountCallback();
        }
      }
    }
    return detected;
  }

  // ---------- 8. 立即执行一次同步检测(页面加载瞬间) ----------
  const initiallyOpen = checkDevTools();

  if (!initiallyOpen) {
    // 控制台未打开:立即挂载
    isMounted = true;
    mountCallback();
  } else {
    // 控制台已打开:延迟挂载,等待关闭时触发
    console.warn('[antiDebug] Console open, mounting delayed.');
  }

  // ---------- 9. 定时轮询(每 50ms) ----------
  setInterval(checkDevTools, 50);

  // ---------- 10. 监听窗口 resize(快速响应) ----------
  let resizeTimer;
  window.addEventListener('resize', () => {
    clearTimeout(resizeTimer);
    resizeTimer = setTimeout(checkDevTools, 30);
  });

  // ---------- 11. 返回销毁函数 ----------
  return function destroy() {
    if (debuggerInterval) {
      clearInterval(debuggerInterval);
      debuggerInterval = null;
    }
    document.getElementById('__anti_debug_overlay')?.remove();
    document.getElementById('__anti_debug_detector')?.remove();
    initialized = false;
    isOpen = false;
    isMounted = false;
    console.log('[antiDebug] Destroyed');
  };
}

核心功能

  • 状态管理:防重复初始化、记录调试状态、控制挂载时机。

  • 环境适配:兼容 SSR,自动等待 DOM 就绪。

  • 快捷拦截:屏蔽右键菜单、F12、Ctrl+Shift+I/J、Ctrl+U。

  • 动态 UI:创建遮罩层 + 隐藏探测元素。

  • 双模检测:尺寸差异(停靠模式)+ 元素偏移(弹出模式)。

  • 主动反制:显示遮罩 + 高频 debugger 循环(每 10ms)。

  • 恢复回调:控制台关闭后隐藏遮罩、停止干扰、触发 Vue 挂载。

  • 持续监控:50ms 轮询 + resize 防抖响应。

  • 资源销毁:清除定时器、移除 DOM、重置标志位。

五、注意事项

性能影响:setInterval 每 50ms 执行一次尺寸计算,且调试状态下每 10ms 执行一次 debugger,对性能有一定损耗,但仅在调试时触发,正常用户无感知。

绕过风险:该方案无法防御高级反反调试手段(如修改 window.outerWidth 的 getter、禁用 debugger 语句等),但足以应对大多数常规尝试。

开发体验:务必仅在 production 环境启用,否则开发时无法使用控制台,影响开发效率。

可扩展性:可根据业务需求调整阈值、检测频率,甚至加入更复杂的指纹校验。

相关推荐
threerocks13 分钟前
AI 原生软件开发生命周期手册 - 如何借助 AI,逐阶段改造软件开发生命周期
前端·javascript·后端
徐小夕24 分钟前
3分钟从想法到Agent上线:我们开源了一款AI可视化工作流“IDE”
前端·算法·github
ly76892 小时前
JavaScript 从入门到进阶:核心语法、异步编程与工程化实践
开发语言·javascript·ecmascript
why技术2 小时前
eli5,我觉得这个全网在吹的技能,使用体验真的很一般啊。
前端·人工智能·后端
excel2 小时前
记录升级 nuxt3 到 nuxt4 记录
前端
剑胆琴心静水深流3 小时前
全栈之路6---web集成与呈现
前端·vue.js·spring boot·分布式·spring·前端框架·npm
前端snow3 小时前
ai agent -- Memory汇总
前端
ITresearchGuest3 小时前
AI 焦虑下,前端该何去何从
前端·人工智能
沙盘客4 小时前
AFSIM 示例解读(03)· 六自由度飞行仿真 six_dof(下):机场运作与弹道导弹投送
java·javascript·经验分享
Codiggerworld4 小时前
Chrome DevTools 隐藏神技:这 5 个调试技巧你可能从来没用过
前端·chrome·chrome devtools