《使用JS-Obfuscator实现前端代码混淆》
本文介绍了一种基于javascript-obfuscator库的H5应用静态资源自动化混淆方案。该方案通过npm安装依赖后,创建obfuscate.js脚本实现对指定目录下JS文件的批量混淆处理,保留vendor前缀框架文件并自动跳过JSON文件。脚本采用递归目录处理方式,提供可配置的混淆参数(如字符串数组加密、自保护机制等)。使用方式为修改package.json的build命令,在Vite构建
一、概况与实现目标
在Web前端开发中,随着H5应用复杂度的提升和商业价值的增加,代码保护变得越来越重要。本文介绍的脚本基于javascript-obfuscator库,旨在为H5应用的静态资源提供自动化混淆方案,主要实现以下目标:
-
对指定目录下的JavaScript文件进行批量混淆
-
保留关键框架文件(如vendor开头的文件)
-
自动跳过JSON等非代码文件
-
实现递归目录处理能力
二、核心实现原理
1. 通过npm安装(推荐)
npm install javascript-obfuscator@4.1.1 --save-dev
2. 手动修改package.json
{
"devDependencies": {
"javascript-obfuscator": "^4.1.1"
}
}
注意:修改完之后 npm i 一下
3. 在package.json同级目录下创建一个js文件(obfuscate.js),文件取名随意
4.完整代码(obfuscate.js内容)
代码中有不懂的配置,请自行网上查询
import fs from 'fs'
import path from 'path'
import jo from 'javascript-obfuscator'
import { fileURLToPath } from 'url'
// 获取当前文件的路径(URL形式),然后转换为文件路径
const __filename = fileURLToPath(import.meta.url)
// 从__filename中获取__dirname
const __dirname = path.dirname(__filename)
// 主要针对h5/assets目录下的资源文件进行处理(这里改成你打包输出的目录)
const outputDir1 = path.join(__dirname, 'h5') // 目标目录
const outputDir2 = path.join(outputDir1, 'assets') // 目标目录
// 定义要排除的前缀
const excludedPrefixes = ['vendor']
// 配置混淆器
const obfuscatorConfig = {
compact: true,
controlFlowFlattening: false,
deadCodeInjection: false,
debugProtection: false,
debugProtectionInterval: 0,
disableConsoleOutput: true,
identifierNamesGenerator: 'hexadecimal',
log: false,
numbersToExpressions: false,
renameGlobals: false,
selfDefending: true,
simplify: true,
splitStrings: false,
stringArray: true,
stringArrayCallsTransform: false,
stringArrayEncoding: [],
stringArrayIndexShift: true,
stringArrayRotate: true,
stringArrayShuffle: true,
stringArrayWrappersCount: 1,
stringArrayWrappersChainedCalls: true,
stringArrayWrappersParametersMaxCount: 2,
stringArrayWrappersType: 'variable',
stringArrayThreshold: 0.75,
unicodeEscapeSequence: false,
rotateStringArray: true,
shuffleStringArray: true,
}
/**
* 查找指定目录下的所有JS文件
* @param {string} dirPath 目录路径
* @returns {Promise<Array<{ path: string }>>} 返回所有JS文件的路径
*/
async function findScriptsInDir(dirPath) {
const scripts = []
const files = fs.readdirSync(dirPath, {
encoding: 'utf8',
withFileTypes: true,
})
for (const file of files) {
const filePath = path.join(dirPath, file.name)
if (file.isDirectory()) {
scripts.push(...(await findScriptsInDir(filePath)))
} else if (
file.name.endsWith('.js') &&
!excludedPrefixes.some((prefix) => file.name.startsWith(prefix))
) {
scripts.push({ path: filePath })
}
}
return scripts
}
/**
* 混淆单个脚本文件
* @param {string} filePath 文件路径
* @returns {Promise<void>}
*/
async function obfuscateScript(filePath) {
try {
const data = fs.readFileSync(filePath, { encoding: 'utf8' })
// 检查是否为JSON文件
if (!isJson(data)) {
const result = jo.obfuscate(data, obfuscatorConfig)
const obfuscatedCode = result.getObfuscatedCode()
fs.writeFileSync(filePath, obfuscatedCode)
console.log(`Obfuscated: ${filePath}`)
}
} catch (error) {
console.error(`Error obfuscating ${filePath}:`, error)
throw error
}
}
/**
* 检查字符串是否为有效的JSON
* @param {string} str 要检查的字符串
* @returns {boolean}
*/
function isJson(str) {
try {
JSON.parse(str)
return true
} catch (error) {
return false
}
}
/**
* 主函数,执行混淆操作
*/
async function main() {
try {
const scripts = await findScriptsInDir(outputDir2)
console.log(`Found ${scripts.length} scripts to obfuscate.`)
for (let i = 0; i < scripts.length; i++) {
await obfuscateScript(scripts[i].path)
console.log(`Progress: ${i + 1}/${scripts.length}`)
}
console.log('Obfuscation completed successfully.')
} catch (error) {
console.error('Obfuscation failed:', error)
}
}
// 启动混淆过程
main()
5. 在package.json文件中
"build": "vite build" 改成 "build": "vite build && node obfuscate.js" 在构建Vite项目后,立即对生成的JS代码进行混淆处理执行obfuscate.js
该混淆方案兼顾了保护强度与可维护性,实际测试表明能有效防范常规逆向分析。建议开发者依据项目需求灵活调整参数配置,并构建"混淆-测试-监控"的全流程保护机制。值得注意的是,代码保护是一个持续优化过程,需结合法律手段与技术升级来构筑全方位的安全防护体系。
更多推荐
所有评论(0)