/** * 当 {@link startAntiDebugGuard} 中某项检测判定为「可疑」时,通过 * {@link AntiDebugOptions.onThreat} 传入的原因标识,便于区分策略或埋点。 */ export type AntiDebugReason = /** {@link detectDebuggerTiming} 认为执行在断点/调试器下被显著拖慢 */ "debugger-timing" /** {@link detectDevToolsByDimensions} 认为窗口/视口尺寸特征像已打开 DevTools */ | "devtools-dimensions" /** {@link detectDevToolsByConsoleTiming} 认为 `console` 调用异常偏慢(与断点无关;默认不启用) */ | "devtools-console-timing"; /** * 分项开关:可单独关闭某一类检测,减轻误报或降低性能开销。 * * 默认两项均为开启(等价于未传 `checks` 或各字段为 `true`)。 * 显式设为 `false` 可关闭对应检测。 */ export interface AntiDebugChecks { /** * 是否启用「debugger 耗时」检测。 * @default true(未传或 `undefined` 时视为开启) */ debuggerTiming?: boolean; /** * 是否启用「窗口 / 视口 / 根元素尺寸差」检测(DevTools dock 场景;**不依赖断点**)。 * @default true */ devToolsDimensions?: boolean; /** * 是否启用「console 调用耗时」检测(DevTools 打开时常更慢;**与「停用断点」无关**)。 * 误报相对多,默认关闭;需更强提示时再开。 * @default false */ devToolsConsoleTiming?: boolean; } /** * {@link installDevToolsUiBlock} / {@link AntiDebugOptions.uiBlock} 的配置。 * * 未写字段在实现里按「尽量拦截快捷键、尽量不挡右键」处理。 */ export interface DevToolsUiBlockOptions { /** * 是否拦截 **F12**。 * @default true */ blockF12?: boolean; /** * 是否拦截常见组合键(如 Ctrl+Shift+I/J/C、Mac Cmd+Opt+I 等)。 * @default true */ blockKeyboardShortcuts?: boolean; /** * 是否拦截**整个页面**的右键菜单(含非 DevTools 场景)。 * @default false */ blockContextMenu?: boolean; /** * 是否拦截 **Ctrl+U**(查看网页源代码)。 * @default false */ blockViewSource?: boolean; } /** {@link AntiDebugOptions.devToolsThresholds} 的字段说明 */ export interface AntiDebugDevToolsThresholds { /** 传给 {@link detectDevToolsByDimensions} 的 `widthGapThreshold` */ widthGap?: number; /** 传给 {@link detectDevToolsByDimensions} 的 `heightGapThreshold` */ heightGap?: number; /** 传给 {@link detectDevToolsByDimensions} 的 `layoutGapThreshold` */ layoutGap?: number; /** 传给 {@link detectDevToolsByConsoleTiming} 的毫秒阈值 */ consoleTimingMs?: number; } /** * {@link startAntiDebugGuard} 的完整配置。 * * **注意**:所有检测均为启发式,不能替代服务端鉴权或代码混淆; * 仅用于提高前端被随意调试、窥探的成本。 */ export interface AntiDebugOptions { /** * 两次完整检测轮询之间的间隔(毫秒)。 * 过小会增加主线程占用与用户耗电感知;过大则反应变慢。 * @default 2000 */ intervalMs?: number; /** * 是否在启动守护后立即执行第一次检测(不等待首个 `interval`)。 * 若设为 `false`,仅按 `intervalMs` 周期执行。 * @default true */ immediate?: boolean; /** * 任一启用的检测返回阳性时调用。常见用途: * - 跳转空白页或登录页 * - 移除敏感 DOM、清空内存中的临时密钥展示 * - 向自有服务端上报(需自行实现请求,本库不内置网络) * * 未提供时,检测仍会周期性执行,但不会触发任何回调(可用于仅做埋点以外的场景时自行组合)。 */ onThreat?: (reason: AntiDebugReason) => void; /** * 为 `true` 时:若当前页面 hostname 被 {@link isLikelyLocalDevHost} * 判为常见本机开发地址(如 `localhost`),则**不启动**守护,避免本地调试时被频繁打断。 * * 部署到正式域名后,该判断通常为 `false`,检测会正常生效。 * 若你希望连本机也强制执行检测,保持默认(`false`)即可。 * @default false */ skipInDevelopment?: boolean; /** 见 {@link AntiDebugChecks} */ checks?: AntiDebugChecks; /** * 微调 DevTools 相关启发式阈值(漏报多时可略调低 `widthGap` / `heightGap`;误报多则调大)。 * 未指定的项使用库内默认值。 */ devToolsThresholds?: AntiDebugDevToolsThresholds; /** * 是否拦截 F12 / 常见打开 DevTools 的快捷键(及可选右键、Ctrl+U)。 * - `true`:使用默认(拦 F12 + 快捷键;**不**默认拦右键,避免整站右键失效)。 * - 对象:见 {@link DevToolsUiBlockOptions}。 * * 与 {@link skipInDevelopment} 同时为真且处于本机 hostname 时,**不会**安装(与轮询检测一致)。 */ uiBlock?: boolean | DevToolsUiBlockOptions; } /** * {@link startAntiDebugGuard} 的返回值:用于在适当时机停止轮询(例如单页应用卸载、用户登出)。 */ export interface AntiDebugHandle { /** * 清除内部 `setInterval`,之后不再执行检测。 * 可重复调用,无副作用。 */ stop: () => void; } /** * 启动防调试守护:在浏览器主线程上以 `setInterval` 周期性执行检测。 * * **行为说明**: * - `window` 不存在(如 Node、部分 SSR 仅服务端执行)时:不启动定时器,返回的 `stop` 为空操作。 * - `skipInDevelopment === true` 且 {@link isLikelyLocalDevHost} 为真:不启动定时器(便于本地开发)。 * - 每次 `tick`:若 `onThreat` 存在且某检测为阳性,则调用 `onThreat(reason)`;同一轮内只触发一次回调。 * * @param options 见 {@link AntiDebugOptions} * @returns {@link AntiDebugHandle},用于 `stop()` 停止轮询 */ export declare function startAntiDebugGuard(options?: AntiDebugOptions): AntiDebugHandle; /** * @module detectDebuggerTiming * 「调试器耗时」检测:利用在断点处暂停时,`debugger` 语句前后时间差会异常变大。 * * **原理简述**:正常执行时,`debugger` 到下一行几乎瞬时;若开发者工具打开且执行停在该行, * 则 `performance.now()` 差值会达到数十毫秒以上(具体与机器与浏览器有关)。 * * **局限性**: * - 用户关闭断点、使用「禁用断点」或极快环境时,可能漏报。 * - 系统卡顿、省电模式也可能拉长耗时,存在极低概率误判(可通过调大 `thresholdMs` 缓解)。 */ /** * 执行一次同步耗时测量:包含一条 `debugger` 语句。 * * @param thresholdMs 超过该毫秒数则视为「可能被调试/停在断点」。默认 `120`。 * @returns `true` 表示耗时超过阈值,**怀疑**处于调试暂停;`false` 表示未超过或未提供 `performance`。 * * @example * ```ts * if (detectDebuggerTiming(150)) { * // 自行处理,例如仅记录埋点 * } * ``` */ export declare function detectDebuggerTiming(thresholdMs?: number): boolean; /** * @module detectDevToolsDimensions * 「窗口尺寸」启发式:许多浏览器在 DevTools 以 dock 形式贴边时, * `outerWidth/Height` 与 `innerWidth/Height` 的差值会明显变大。 * * 另补充 `innerWidth - documentElement.clientWidth` 等差值,用于在 **outer-inner** * 阈值边缘时提高对「已打开 DevTools 但停用断点」场景的灵敏度(仍无法覆盖**独立窗口** undock)。 * * **非绝对可靠**:分屏、高分屏、缩放、移动端、无边框窗口等可能误报或漏报。 */ /** {@link detectDevToolsByDimensions} 的可选参数(全部有默认值) */ export interface DevToolsDimensionOptions { /** `outerWidth - innerWidth` 超过该像素则视为阳性 */ widthGapThreshold?: number; /** `outerHeight - innerHeight` 超过该像素则视为阳性 */ heightGapThreshold?: number; /** * `innerWidth - document.documentElement.clientWidth`(或高度侧)超过该值则视为阳性。 * 用于捕捉仅靠 outer-inner 未过阈值但视口与根元素不一致的情况(略增灵敏度)。 */ layoutGapThreshold?: number; } /** * 根据窗口 / 视口 / 根元素尺寸差,判断 DevTools **可能**已打开(dock 场景为主)。 * * 兼容旧调用方式:`detectDevToolsByDimensions(160, 300)` 两个数字参数。 */ export declare function detectDevToolsByDimensions(widthOrOptions?: number | DevToolsDimensionOptions, heightGapThreshold?: number): boolean; /** * @module detectDevToolsConsoleTiming * 在 DevTools 打开(尤其 Console 面板)时,部分浏览器对 `console.*` 的调用 * 会比关闭时更慢。与 `debugger` 无关,**不受「停用断点」影响**。 * * **局限**:误报/漏报均存在(省电模式、扩展、无 DevTools 但 Console 被 hook 等); * 默认在守护中**关闭**,需显式 `checks.devToolsConsoleTiming: true` 再启用。 */ /** * @param thresholdMs 单次 `console.debug` 耗时超过该值则视为可疑(毫秒)。 * @returns `true` 表示耗时超过阈值;无 `performance`/`console` 时返回 `false`。 */ export declare function detectDevToolsByConsoleTiming(thresholdMs?: number): boolean; /** * 与「是否跳过本地开发机上的守护」相关的环境判断,供 {@link startAntiDebugGuard} * 在 `skipInDevelopment === true` 时使用。 */ /** * 判断当前页面是否运行在常见的本地开发用 hostname 上。 * * 命中时包括:`localhost`、`127.0.0.1`、`[::1]`、`0.0.0.0`、以及以 `.local` 结尾的主机名 *(部分 mDNS 环境)。 * * @returns 在浏览器中且 hostname 匹配上述规则时为 `true`;无 `location`(如部分 Worker/SSR)为 `false`。 */ export declare function isLikelyLocalDevHost(): boolean; /** * 可选:将全局 `console` 上若干方法替换为空函数,使依赖脚本难以在控制台输出结构化信息。 * **不能**防止用户阅读源码或 Network 面板;仅增加「随手打 log 」的阻力。 */ export type ConsoleMethod = keyof Console; export interface NoopConsoleOptions { /** * 要替换的 `console` 方法名;未传时使用 {@link DEFAULT_NOOP_METHODS}。 */ methods?: ConsoleMethod[]; } /** * 安装 noop console:保存原始实现,返回 `uninstall` 函数。 * * - 在单元测试或需要恢复调试时,务必调用返回的函数。 * - 若某方法在运行环境中不存在,会跳过。 * * @param options 可选,指定要替换的方法集合。 * @returns 调用后恢复所有被替换方法的函数。 */ export declare function installNoopConsole(options?: NoopConsoleOptions): () => void; /** * 注册 `keydown`(捕获阶段)与可选的 `contextmenu`。 * * @param options 未传字段见 {@link DevToolsUiBlockOptions} 默认值说明。 * @returns 卸载函数:移除监听,可重复调用无副作用。 */ export declare function installDevToolsUiBlock(options?: DevToolsUiBlockOptions): () => void; export {};