概述
JSShield 是一款专业的 JavaScript 代码混淆与保护服务,提供多种混淆策略和虚拟机保护(JSVMP)能力。
本文档面向集成开发者,介绍如何通过 API 调用 JSShield 的混淆服务。如果你只是想在线使用,请访问 Web 控制台。
核心能力
- 字符串数组加密 — 将代码中的字符串提取到加密数组中,通过动态解码访问
- 控制流平坦化 — 将线性代码转换为状态机,增加逆向难度
- 死代码注入 — 插入无意义的代码分支,干扰静态分析
- JSVMP 虚拟机保护 — 将核心函数编译为自定义字节码,在 VM 中运行
- 反调试保护 — 检测开发者工具并触发保护机制
接口地址
所有 API 接口的基础地址:https://jsshield.lltxj.top
示例:混淆接口完整地址为 https://jsshield.lltxj.top/api/v1/obfuscate
https://jsshield.lltxj.top/api/v1/obfuscate
使用限制
- 并发限制:每个 IP 同时只能有 1 个请求在处理中
- 频率限制:每个 IP 每分钟最多 60 次请求
- 大小限制:单次请求最大 10MB
- 认证要求:必须携带有效的
X-API-Token请求头
获取令牌
调用 API 需要令牌(Token)进行身份验证。获取方式如下:
- 访问 Web 控制台首页
- 点击顶部导航栏的「生成令牌」按钮,或滚动到页面底部的 Token 区域
- 确认使用须知后系统自动完成验证并生成令牌
- 复制令牌保存到环境变量或配置文件中
- 令牌有效期为 30 天,过期后需重新生成
- 令牌是无状态的,可多设备共用
- 也可以点击页面右上角的「生成令牌」按钮快速跳转到首页 Token 区域
请勿将令牌提交到公开仓库。建议通过环境变量(如 JSSHIELD_TOKEN)传入构建流程。
快速调用示例
使用获取到的令牌调用混淆接口。以下是一个完整的请求示例:
认证方式
所有 API 请求需要在请求头中携带令牌。这是唯一的认证方式,不支持 Basic Auth 或 OAuth。
令牌缺失或无效时返回 401 Unauthorized:
{
"success": false,
"error": "Unauthorized",
"message": "Invalid or missing API token"
}
混淆接口
POST /api/v1/obfuscate
https://jsshield.lltxj.top/api/v1/obfuscate
核心混淆接口,将 JavaScript 源代码混淆为受保护的代码。
请求参数
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
sourceCode | string | 是 | 待混淆的 JavaScript 源代码(纯文本) |
preset | string | 否 | 预设模式名称,如 high、ultimate |
options | object | 否 | 自定义混淆选项,会覆盖 preset 中的同名配置 |
target | string | 否 | 目标环境:默认 browser,可选 node、service-worker |
请求示例
{// 使用预设模式快速混淆
"sourceCode": "function hello(name) { return 'Hello ' + name; }",// 待混淆源码
"preset": "high"// 预设名称:low / default / medium / high / jsvmp / ultimate 等
}
{// 通过 options 精细控制每个混淆选项
"sourceCode": "function hello(name) { return 'Hello ' + name; }",
"options": {
"compact": true,// 压缩输出代码
"stringArrayEncoding": ["rc4"],// RC4 加密字符串数组
"selfDefending": true,// 启用自我保护
"debugProtection": true// 启用反调试保护
}
}
# cURL 命令行调用示例
curl -X POST https://jsshield.lltxj.top/api/v1/obfuscate \
-H "Content-Type: application/json" \
-H "X-API-Token: YOUR_TOKEN_HERE" \
-d '{"sourceCode":"function hi(){return 1;}","preset":"high"}'
preset 与 options 的优先级
同时传入时,options 会覆盖 preset 中的同名配置。例如以 high 为基础额外开启调试保护:
{ "preset": "high", "options": { "debugProtection": true } }
响应示例(成功)
{
"success": true,
"code": "var _0x1a2b=[...];function hello(_0x3c4d){return _0x1a2b[0]+_0x3c4d;}",// 混淆后的代码
"engineFingerprint": "a1b2c3d4e5f67890",// 引擎指纹,用于缓存 key 计算
"stats": {
"originalSize": 52,// 原始字节大小
"obfuscatedSize": 89,// 混淆后字节大小
"ratio": "1.71",// 膨胀比例
"elapsedMs": 15// 处理耗时(毫秒)
}
}
响应示例(失败)
{
"success": false,
"error": "Invalid token",
"message": "API令牌无效或已过期,请前往首页重新生成"
}
响应头
| 响应头 | 说明 |
|---|---|
X-JSShield-Version | 服务端版本号(如 4.1.0),用于兼容性判断 |
X-JSShield-Fingerprint | 引擎指纹(SHA256 前 16 位),引擎代码变化时自动更新 |
指纹仅取决于混淆引擎的实际代码逻辑,与版本号、构建时间无关。当 JSShield 服务端更新混淆引擎代码时,内容哈希会自动变化;仅更新版本号但代码未变时,指纹不变。此值可用于 CI/CD 缓存策略的缓存 key 计算。
版本接口
GET /api/v1/version
https://jsshield.lltxj.top/api/v1/version
获取当前混淆引擎的版本和指纹信息。公开接口,无需携带令牌,适用于 CI/CD 构建开始时快速获取引擎指纹以计算缓存 key、检测服务端引擎是否更新。
此接口为公开端点,仅返回只读的公开信息(版本号 + 引擎指纹哈希),不涉及代码混淆操作。作为缓存失效检测入口,在 CI/CD 流程中需要无门槛调用,避免循环依赖。
健康检查
GET /api/v1/health
https://jsshield.lltxj.top/api/v1/health
用于检测服务连通性,不限制 HTTP 方法。适合在部署脚本或监控系统中使用。
{
"status": "ok",// 服务状态
"service": "JSShield Obfuscation API",// 服务标识
"version": "6.1.5",// 当前版本
"timestamp": "2025-01-01T00:00:00.000Z",// 服务器时间
"endpoints": {
"internal": "/api/obfuscate",// 内部接口路径
"public": "/api/v1/obfuscate"// 公开接口路径
}
}
状态码说明
| 状态码 | 含义 | 说明 | 解决方案 |
|---|---|---|---|
200 | success | 请求成功 | — |
400 | BAD_REQUEST | 请求参数错误 | 检查 sourceCode 是否存在且为字符串 |
401 | UNAUTHORIZED | 令牌无效或缺失 | 前往首页重新生成令牌 |
403 | FORBIDDEN | 挑战过期或验证失败 | 重新发起 challenge 流程 |
413 | Request too large | 超过 10MB 上限 | 减小源文件体积或分包处理 |
429 | TOO_MANY_REQUESTS | 速率限制或并发超限 | 降低请求频率,响应体含 retryAfter 字段 |
500 | INTERNAL_ERROR | 服务器内部错误 | 检查源代码语法是否合法 |
并发限制详情
每个 IP 同时只能有 1 个请求在处理中。并发超限时返回 429,响应体包含 retryAfter: 5(秒),表示建议等待时间后重试。
限流策略
| 接口类型 | 频率限制 | 说明 |
|---|---|---|
公共 API (/api/v1/*) | 60 次/分钟/IP | 面向外部用户的接口 |
内部 API (/api/*) | 30 次/分钟/IP | 面向内部系统的接口 |
超限时返回 429 Too Many Requests 状态码。建议在客户端实现指数退避重试策略。
预设列表
选择预设模式可以快速应用最佳实践配置。也可通过 options 覆盖特定选项。
low · 低强度
基础混淆 + 自我保护,适合对性能要求高的场景
default · 默认
标准混淆配置,平衡安全性和性能
medium · 中强度
控制流平坦化 + 死代码注入 + 字符串拆分
high · 高强度
全部基础选项开启,适合商业产品保护
jsvmp · 虚拟机保护
将核心函数编译为字节码,在自定义虚拟机中运行
anti-debug · 反调试
多层反调试:DevTools/Console/时间检测 + 反内存转储
anti-reverse · 防逆向
反 LLM 保护 + 诱饵函数 + 控制流平坦化
ultimate · 终极保护
三重防护全开:JSVMP + 反调试 + 防逆向
预设组合
通过 preset + options 实现组合。例如在 high 基础上叠加反调试:
{// 以 high 为基础,额外开启调试保护和定时检测
"preset": "high",
"options": {
"debugProtection": true,// 开启无限 Debuger 检测
"debugProtectionInterval": 2000// 每 2 秒检测一次
}
}
各预设的完整选项可通过 GET /api/v1/options 查询。
性能参考
以下数据基于 10KB 典型代码的测试结果(仅供参考,实际因代码复杂度而异):
| 预设 | 体积膨胀 | 运行时性能损失 |
|---|---|---|
| low | +30~50% | <5% |
| medium | +100~200% | 10~20% |
| high | +300~500% | 30~50% |
| jsvmp / ultimate | +500~1000% | JSVMP 函数慢 5~20 倍 |
基础选项
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
target | string | "browser" | 目标运行环境 |
compact | boolean | true | 压缩输出,移除多余空白 |
simplify | boolean | true | 简化代码结构 |
字符串数组
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
stringArray | boolean | true | 启用字符串数组提取 |
stringArrayEncoding | array | [] | 编码方式:base64、rc4,可组合如 ["base64","rc4"] |
stringArrayThreshold | number | 0.75 | 字符串提取率 (0~1),越低提取越多 |
splitStrings | boolean | false | 将长字符串拆分为多个片段 |
控制流保护
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
controlFlowFlattening | boolean | false | 控制流平坦化,将 if/else 转为 switch 状态机 |
deadCodeInjection | boolean | false | 注入死代码块,干扰静态分析 |
numbersToExpressions | boolean | false | 将数字字面量转为复杂表达式 |
JSVMP 保护
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
jsvmpProtection | boolean | false | 启用 JSVMP 字节码虚拟机保护 |
jsvmpAutoDetect | boolean | true | 自动检测需要保护的函数(非下划线开头且长度>2) |
jsvmpTargetFunctions | array | [] | 手动指定需要 VM 保护的函数名列表 |
jsvmpDynamicOpcodes | boolean | false | 每次编译生成不同的操作码映射 |
反调试选项
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
debugProtection | boolean | false | 基础调试保护(无限 Debugger 检测) |
selfDefending | boolean | false | 自我保护,检测被篡改时触发自毁 |
disableConsoleOutput | boolean | false | 禁用 console.log/warn/error 输出 |
advancedDebugProtection | boolean | false | 高级反调试(DevTools/Console/时间检测) |
antiMemoryDump | boolean | false | 反内存转储,防止内存快照分析 |
完整选项表
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
target | string | "browser" | 目标环境 |
compact | boolean | true | 压缩输出 |
simplify | boolean | true | 简化代码结构 |
stringArray | boolean | true | 字符串数组 |
stringArrayEncoding | array | [] | 编码方式 |
stringArrayThreshold | number | 0.75 | 提取率 (0~1) |
splitStrings | boolean | false | 拆分长字符串 |
controlFlowFlattening | boolean | false | 控制流平坦化 |
deadCodeInjection | boolean | false | 死代码注入 |
numbersToExpressions | boolean | false | 数字转表达式 |
selfDefending | boolean | false | 自我保护 |
debugProtection | boolean | false | 调试保护 |
advancedDebugProtection | boolean | false | 高级反调试 |
antiMemoryDump | boolean | false | 反内存转储 |
disableConsoleOutput | boolean | false | 禁用 console |
jsvmpProtection | boolean | false | JSVMP 保护 |
jsvmpAutoDetect | boolean | true | 自动检测函数 |
jsvmpTargetFunctions | array | [] | 手动指定函数名 |
jsvmpDynamicOpcodes | boolean | false | 动态操作码 |
antiLlmProtection | boolean | false | 反 AI/LLM 分析 |
decoyFunctions | boolean | false | 注入诱饵函数 |
Webpack 集成
- 默认开启:
ENABLE_API_OBFUSCATION = true - 失败即终止:API 请求失败时构建流程立即终止,绝不输出未混淆代码
- Webpack / Vite / Rollup:通过
throw e抛出异常中断构建 - Node.js 脚本:通过
process.exit(1)终止进程 - 跳过混淆:设置
ENABLE_API_OBFUSCATION = false
Vite 集成
Rollup 集成
Rollup 插件结构与 Vite 完全相同(Vite 底层使用 Rollup)。复用上面的 obfuscateCode 函数,仅在钩子上切换:
esbuild 集成
Node.js 脚本
JSVMP 使用指南
JSVMP(JavaScript Virtual Machine Protection)将核心函数编译为自定义字节码,在虚拟机中运行。这是最高级别的保护手段。
自动检测规则
当 jsvmpAutoDetect: true(默认)时,自动识别符合以下条件的函数:
- 函数名不以
_开头(约定私有函数不受保护) - 函数名长度大于 2
- 包括函数声明、函数表达式、类方法、箭头函数赋值
手动指定保护范围
通过 jsvmpTargetFunctions 精确指定需要保护的函数名:
{// 只保护这两个核心函数
"jsvmpProtection": true,
"jsvmpAutoDetect": false,// 关闭自动检测
"jsvmpTargetFunctions": ["encryptData", "validateToken"]
}
JSVMP 保护的函数不支持 Source Map。调试时建议先用 default 或 medium 预设测试功能正确性,确认无误后再切换到 JSVMP 预设。
客户端缓存策略
在 CI/CD 构建流程中,相同的源代码 + 相同的混淆选项会产生相同的混淆结果。通过内容寻址缓存(Content-Addressed Cache),可以避免重复调用 API,显著降低构建时间和服务器负载。
核心原理
缓存 key 由 SHA256(源代码 + 混淆选项 + 引擎指纹) 三元组生成。任一因素变化都会导致缓存失效:
工作流程
构建开始
|
│ 1. GET /api/v1/version → 获取 engineFingerprint
|
│ 2. hash = SHA256(源代码 + 选项 + engineFingerprint)
|
├─ 3. 检查 .jsshield-cache/{hash}.js 是否存在?
| ├─ 存在 → 读取缓存,跳过 API 调用
| └─ 不存在 → 调用 POST /api/v1/obfuscate
| ├─ 成功 → 写入缓存 + 输出结果
| └─ 失败 → 终止构建(不输出未u6DF7;u6DC6;代码)
|
└─ 构建ָ成
利弊分析
| 维度 | 说明 | 应对策略 |
|---|---|---|
| ✅ 节省 API 调用 | 相同输入不重复调用 | — |
| ✅ 加速构建 | 缓存命中从秒级降到毫秒级 | — |
| ✅ 持久化缓存 | 独立于 dist/ 目录 | .gitignore 加入 .jsshield-cache/ |
| ✅ 天然去重 | 内容寻址,相同代码不重复存储 | — |
| ⚠️ 引擎更新 | 服务端算法更新后旧缓存可能过时 | 指纹基于引擎代码哈希,代码变化时自动失效;仅版本号变化不影响 |
| ⚠️ 缓存膨胀 | 长期积累占用磁盘空间 | 定期清理超过 30 天的缓存,或限制总大小 500MB |
| ⚠️ 多人协作 | 各团队成员各自维护本地缓存 | 正确做法,不应共享。首次构建即生成本地缓存 |
| ⚠️ seed=0 随机性 | 每次混淆结果不同但语义等价 | 语义等价即可命中缓存 |
| ⚠️ 指纹获取失败 | Version API 不可用时无法获取指纹 | 降级使用 'unknown' 作为指纹,下次构建自动修正 |
将 .jsshield-cache/ 加入 .gitignore,缓存目录不应提交到 Git 仓库。它是本地构建优化,每个开发者的首次构建会自动生成缓存。
TypeScript 支持
JSShield API 本身不直接处理 TypeScript。推荐的构建流水线如下:
- 使用
tsc或esbuild将 TypeScript 编译为 JavaScript - 对编译后的 JavaScript 调用 JSShield API 进行混淆
- 确保
target选项与您的实际运行环境匹配
Source Map 说明
JSShield 不支持生成 Source Map。这是一个设计决策——Source Map 会暴露原始代码的结构信息,与代码混淆保护的目的相悖。
建议的调试策略:
- 开发环境使用
low或default预设(保留可读性) - 功能测试通过后再切换到
high或ultimate预设部署生产 - 必要时设置
disableConsoleOutput: false保留日志输出辅助排查问题
最佳实践
- 生产环境推荐使用
high或ultimate预设获得最佳保护效果 - 核心算法/加密逻辑推荐使用
jsvmp预设获得最高级别的虚拟机保护 - CI/CD 构建时务必使用内容寻址缓存(基于 hash),避免重复请求浪费配额
- 本地开发阶段用
low预设加快构建速度,发布前切高强度 - 串行处理多个文件—— 并发限制为 1/IP
- 网络请求设置 60 秒超时防止长时间挂起
- 绝对不要将令牌提交到公开仓库,统一通过环境变量
JSSHIELD_TOKEN传入