Vue项目中Vite以及Webpack代码混淆处理

前言

关于代码混淆网上案例铺天盖地,90%以上都是Webpack相关来处理代码混淆,对于Vite的案例少之又少,在解决vite项目代码混淆我花了一些时间来找合适的插件区处理这个问题,最终选择rollup-plugin-obfuscator。另外第四章节介绍了Webpack 处理代码混淆方案。

npm 地址:链接直达

githup 地址:链接直达

一、插件介绍

rollup-plugin-obfuscator 是 Rollup 构建工具的一个插件,用于对 JavaScript 代码进行混淆和压缩。它的主要作用是增加 JavaScript 代码的安全性和减小生成文件的大小。

1、原理和工作方式:

  • 代码混淆:插件通过采用各种技巧来混淆 JavaScript 代码,使其变得难以理解和逆向工程。这些技巧包括变量名重命名、函数提取、字符串替换等。例如,它可以将原始代码中的变量名和函数名改为无意义的名称,从而增加代码的复杂性。

  • 代码压缩:除了混淆,插件还可以对代码进行压缩,删除不必要的空格、注释和缩短变量名,以减小生成文件的大小。这有助于加快网页加载速度。

  • 选项配置:插件通常提供了许多选项配置,允许开发者自定义混淆和压缩的程度。这些选项包括设置要保留的函数、排除特定文件或模块等。

2、特点:

  • 安全性增强:混淆使代码更难以被他人理解,降低了代码被盗用、破解或修改的风险。这对于保护知识产权和敏感数据非常有用。

  • 文件大小优化:插件通过代码压缩有助于减小生成文件的大小,从而减少了网络传输时间和提高了网页加载速度。

  • 适用于前端项目:rollup-plugin-obfuscator 特别适用于前端项目,如网页应用程序,以增加客户端端代码的安全性。

  • 可定制性:插件通常提供广泛的选项来满足不同项目的需求,开发者可以根据具体情况进行配置。

  • 保留功能性:混淆后的代码通常会保留原有的功能性,确保应用程序仍然能够正常运行。

混淆并不是绝对的安全措施,有经验的黑客仍然可能尝试解密代码。因此,在需要更高安全性的情况下,还需要采取其他措施,如服务器端验证和加密。

二、Vite混淆处理

项目环境:Vue3+Vite

1、安装

javascript 复制代码
yarn add --dev rollup-plugin-obfuscator javascript-obfuscator
或者
npm install --save-dev rollup-plugin-obfuscator javascript-obfuscator

在打包时候还会报错,需要安装下面的依赖

javascript 复制代码
yarn add javascript-obfuscator -D

2、引入

vite.config.ts中引入插件,并进行设置

javascript 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import obfuscator from 'rollup-plugin-obfuscator';
export default defineConfig({
  // base: "",
  build: {
    minify: 'esbuild', // 默认
  },
  esbuild: {
    drop: ['console', 'debugger'],//打包去除
  },
  plugins: [
    vue(),
    obfuscator({
      global:false,
      // options配置项实际为 javascript-obfuscator 选项,具体可查看https://github.com/javascript-obfuscator/javascript-obfuscator
      options: {
        compact: true,
        controlFlowFlattening: true,
        controlFlowFlatteningThreshold: 0.75,
        numbersToExpressions: true,
        simplify: true,
        stringArrayShuffle: true,
        splitStrings: true,
        splitStringsChunkLength: 10,
        rotateUnicodeArray: true,
        deadCodeInjection: true,
        deadCodeInjectionThreshold: 0.4,
        debugProtection: false,
        debugProtectionInterval: 2000,
        disableConsoleOutput: true,
        domainLock: [],
        identifierNamesGenerator: "hexadecimal",
        identifiersPrefix: "",
        inputFileName: "",
        log: true,
        renameGlobals: true,
        reservedNames: [],
        reservedStrings: [],
        seed: 0,
        selfDefending: true,
        sourceMap: false,
        sourceMapBaseUrl: "",
        sourceMapFileName: "",
        sourceMapMode: "separate",
        stringArray: true,
        stringArrayEncoding: ["base64"],
        stringArrayThreshold: 0.75,
        target: "browser",
        transformObjectKeys: true,
        unicodeEscapeSequence: true,

        domainLockRedirectUrl: "about:blank",
        forceTransformStrings: [],
        identifierNamesCache: null,
        identifiersDictionary: [],
        ignoreImports: true,
        optionsPreset: "default",
        renameProperties: false,
        renamePropertiesMode: "safe",
        sourceMapSourcesMode: "sources-content",
       
        stringArrayCallsTransform: true,
        stringArrayCallsTransformThreshold: 0.5,
       
        stringArrayIndexesType: ["hexadecimal-number"],
        stringArrayIndexShift: true,
        stringArrayRotate: true,
        stringArrayWrappersCount: 1,
        stringArrayWrappersChainedCalls: true,
        stringArrayWrappersParametersMaxCount: 2,
        stringArrayWrappersType: "variable",
      }
    })
  ]
})

3、配置项解释

下面的列表是 rollup-plugin-obfuscator 插件的配置选项列表,每个选项都用于定制代码混淆和压缩的方式。以下是每个选项的解释:

配置项 描述
global 这是一个布尔值,如果设置为 false,将禁用混淆全局作用域的代码。
compact 一个布尔值,如果设置为 true,则启用代码的紧凑模式,删除不必要的空白字符和注释。
controlFlowFlattening 启用控制流混淆,使代码的控制流程变得更加复杂,从而增加代码的难以理解性。
controlFlowFlatteningThreshold 控制流混淆的阈值,影响混淆程度。
numbersToExpressions 如果设置为 true,将数字转换为表达式,增加代码的复杂性。
simplify 启用简化,用于删除不必要的代码。
stringArrayShuffle 打乱字符串数组,使字符串更难以理解。
splitStrings 将字符串拆分成小块,增加代码的复杂性。
splitStringsChunkLength 控制字符串拆分的块大小。
rotateUnicodeArray 旋转 Unicode 字符数组,增加代码的混淆度。
deadCodeInjection 开启膨胀,插入死代码,使代码更复杂,阻碍逆向工程。
deadCodeInjectionThreshold 死代码注入的阈值。
debugProtection 如果设置为 true,将启用调试保护。
debugProtectionInterval 控制调试保护的间隔。
disableConsoleOutput 禁用控制台输出。
domainLock 限制脚本运行的域名列表。
identifierNamesGenerator 控制混淆后的标识符名称生成方式,如 "hexadecimal"。
identifiersPrefix 标识符前缀,可增加混淆度。
inputFileName 输入文件名。
log 是否启用日志记录。
renameGlobals 是否重命名全局变量。
reservedNames 保留的标识符名字列表。
reservedStrings 保留的字符串列表。
seed 用于生成随机数的种子。
selfDefending 如果设置为 true,将启用自我保护模式。
sourceMap 是否生成源映射文件。
stringArray 是否启用字符串数组混淆。
stringArrayEncoding 字符串数组的编码方式,如 "base64"。
stringArrayThreshold 控制字符串数组混淆的阈值。
target 目标环境,如 "browser".
transformObjectKeys 是否转换对象键名。
unicodeEscapeSequence 启用 Unicode 转义序列。
domainLockRedirectUrl 域名锁定重定向的URL。
forceTransformStrings 强制转换字符串的列表。
identifierNamesCache 标识符名称的缓存。
identifiersDictionary 标识符字典,用于自定义标识符名称。
ignoreImports 是否忽略导入的模块。
optionsPreset 预定义的配置选项集,如 "default".
renameProperties 是否重命名对象属性。
renamePropertiesMode 对象属性重命名模式,如 "safe".
sourceMapSourcesMode 源映射的模式。
stringArrayCallsTransform 是否转换字符串数组调用。
stringArrayCallsTransformThreshold 字符串数组调用转换的阈值。
stringArrayIndexesType 字符串数组索引的类型,如 "hexadecimal-number".
stringArrayIndexShift 是否进行字符串数组索引的位移。
stringArrayRotate 是否旋转字符串数组。
stringArrayWrappersCount 字符串数组包装器的数量。
stringArrayWrappersChainedCalls 是否启用字符串数组包装器的链接调用。
stringArrayWrappersParametersMaxCount 字符串数组包装器的参数最大数量。
stringArrayWrappersType 字符串数组包装器的类型。

注意,当项目比较庞大时,不建议开启膨胀,也就是deadCodeInjection取值为false,不需要设置deadCodeInjectionThreshold的值

三、Vite混淆处理可能会出现的异常问题

1、Uncaught SyntaxError: Unexpected token '<'

打包之后,部署到服务器后,控制台报错:Uncaught SyntaxError: Unexpected token '<'

点开之后,显示如下: 经过查询资料,发现是Vue内部静态资源文件引用出问题了。 出错地方的代码如下:

javascript 复制代码
let transWorker = new Worker(
    new URL("../until/transcode.worker.js", import.meta.url)
);

解决办法:将transcode.worker.js放到public下的static文件夹下,然后对上面代码修改:

javascript 复制代码
let transWorker = new Worker(
    new URL("/static/transcode.worker.js", import.meta.url)
);

四、webpack混淆处理

Vue2项目中使用Webpack代码混淆方案使用webpack-obfuscator + javascript-obfuscator

1、查看Webpack的版本

先查看Webpack的版本,不同webpack版本安装的webpack-obfuscator版本不同。

webpack4.x 使用2.x的 webpack-obfuscator webpack5.x 使用3.x的 webpack-obfuscator

javascript 复制代码
yarn list webpack

2、安装

  • webpack4.x
javascript 复制代码
yarn add webpack-obfuscator@2.6.0 javascript-obfuscator -D
  • webpack5.x
javascript 复制代码
yarn add webpack-obfuscator javascript-obfuscator -D

3、配置

// vue.config.js

javascript 复制代码
var obfuscator = require('webpack-obfuscator');

module.exports = {
  configureWebpack: {
    plugins: [
      new obfuscator({
        rotateStringArray: true,
        /**[] 可以配置 排除混淆的文件 */
      }, [])
    ]
  },
}

具体配置项可参考第二章的第三小节。此配置与上面使用Vite几乎相同。

javascript 复制代码
{
  // 压缩,无换行
  compact: true,
  // 是否启用控制流扁平化(降低1.5倍的运行速度)
  controlFlowFlattening: false,
  // 应用概率;在较大的代码库中,建议降低此值,因为大量的控制流转换可能会增加代码的大小并降低代码的速度。
  controlFlowFlatteningThreshold: 0.75,
  // 随机的死代码块(增加了混淆代码的大小)
  deadCodeInjection: false,
  // 死代码块的影响概率
  deadCodeInjectionThreshold: 0.4,
  // 此选项几乎不可能使用开发者工具的控制台选项卡
  debugProtection: false,
  // 如果选中,则会在"控制台"选项卡上使用间隔强制调试模式,从而更难使用"开发人员工具"的其他功能。
  debugProtectionInterval: false,
  // 通过用空函数替换它们来禁用console.log,console.info,console.error和console.warn。这使得调试器的使用更加困难。
  disableConsoleOutput: false,
  //锁定混淆的源代码,使其仅在特定域和/或子域上运行。这使得某人只需复制并粘贴您的源代码并在其他地方运行就变得非常困难。
  domainLock: [],
  //标识符的混淆方式 hexadecimal(十六进制) mangled(短标识符)
  identifierNamesGenerator: 'hexadecimal',
  //全局标识符添加特定前缀,在混淆同一页面上加载的多个文件时使用此选项。此选项有助于避免这些文件的全局标识符之间发生冲突。为每个文件使用不同的前缀
  identifiersPrefix: '',
  inputFileName: '',
  // 允许将信息记录到控制台。
  log: false,
  // 是否启用全局变量和函数名称的混淆
  renameGlobals: false,
  // 禁用模糊处理和生成标识符
  reservedNames: [],
  // 禁用字符串文字的转换
  reservedStrings: [],
  // 通过固定和随机(在代码混淆时生成)的位置移动数组。这使得将删除的字符串的顺序与其原始位置相匹配变得更加困难。如果原始源代码不小,建议使用此选项,因为辅助函数可以引起注意。
  rotateStringArray: true,
  // 混淆后的代码,不能使用代码美化,同时需要配置 cpmpat:true;
  seed: 0,
  selfDefending: false,
  sourceMap: false,
  sourceMapBaseUrl: '',
  sourceMapFileName: '',
  sourceMapMode: 'separate',
  // 删除字符串文字并将它们放在一个特殊的数组中
  stringArray: true,
  // 编码的所有字符串文字stringArray使用base64或rc4并插入即用其解码回在运行时的特殊代码。true(boolean):stringArray使用编码值base64;false(boolean):不编码stringArray值;'base64'(string):stringArray使用编码值base64;'rc4'(string):stringArray使用编码值rc4。大约慢30-50%base64,但更难获得初始值。建议禁用unicodeEscapeSequence带rc4编码的选项以防止非常大的混淆代码。
  stringArrayEncoding: false,
  // 调整字符串文字将插入stringArray的概率
  stringArrayThreshold: 0.75,
  // 您可以将混淆代码的目标环境设置为以下之一:Browser;Browser No Eval;Node
  target: 'browser',
  // 是否启用混淆对象键
  transformObjectKeys: false,
  // 允许启用/禁用字符串转换为unicode转义序列。Unicode转义序列大大增加了代码大小,并且可以轻松地将字符串恢复为原始视图。建议仅对小型源代码启用此选项。
  unicodeEscapeSequence: false
}
相关推荐
向前看-15 分钟前
验证码机制
前端·后端
燃先生._.1 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖2 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235242 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240253 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar3 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人4 小时前
前端知识补充—CSS
前端·css
GISer_Jing4 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试
m0_748245524 小时前
吉利前端、AI面试
前端·面试·职场和发展