1e41f4b71Sopenharmony_ci# ArkGuard源码混淆工具
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci## 代码混淆简介
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci针对工程源码的混淆可以降低工程被破解攻击的风险,缩短代码的类与成员的名称,减小应用的大小。  
6e41f4b71Sopenharmony_ciDevEco Studio原先默认开启代码混淆功能,会对API 10及以上版本的Stage模型、[编译模式为release](#说明)时自动进行代码混淆,其仅对参数名和局部变量名进行混淆。  
7e41f4b71Sopenharmony_ci**从DevEco Studio 5.0.3.600开始,新建工程默认关闭代码混淆功能,如果在模块配置文件build-profile.json5开启代码混淆,混淆规则配置文件obfuscation-rules.txt中默认开启-enable-property-obfuscation、-enable-toplevel-obfuscation、-enable-filename-obfuscation、-enable-export-obfuscation四项推荐选项,开发者可进一步在obfuscation-rules.txt文件中更改配置。**
8e41f4b71Sopenharmony_ci
9e41f4b71Sopenharmony_ci### 使用约束
10e41f4b71Sopenharmony_ci
11e41f4b71Sopenharmony_ci* 仅支持Stage工程
12e41f4b71Sopenharmony_ci* 编译模式为release
13e41f4b71Sopenharmony_ci* 模块及模块依赖的HAR均未配置关闭混淆的规则`-disable-obfuscation`
14e41f4b71Sopenharmony_ci
15e41f4b71Sopenharmony_ci### 混淆范围
16e41f4b71Sopenharmony_ci
17e41f4b71Sopenharmony_ci在应用工程中,代码混淆支持以下格式文件混淆,混淆后的缓存文件保存在模块目录下的build/[...]/release目录下。
18e41f4b71Sopenharmony_ci
19e41f4b71Sopenharmony_ci* ArkTS文件
20e41f4b71Sopenharmony_ci* TS文件
21e41f4b71Sopenharmony_ci* JS文件
22e41f4b71Sopenharmony_ci
23e41f4b71Sopenharmony_ci## 开启代码混淆
24e41f4b71Sopenharmony_ci
25e41f4b71Sopenharmony_ci代码混淆能力已在系统中集成,可通过以下方式在DevEco Studio开启使用。
26e41f4b71Sopenharmony_ci
27e41f4b71Sopenharmony_ci代码混淆目前只提供名称混淆的能力(因为其它混淆能力会劣化性能)。 开启代码混淆可以混淆以下名称:
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci* 参数名和局部变量名  
30e41f4b71Sopenharmony_ci* 顶层作用域的名称  
31e41f4b71Sopenharmony_ci* 属性名称
32e41f4b71Sopenharmony_ci* 导出名称
33e41f4b71Sopenharmony_ci* 文件名称
34e41f4b71Sopenharmony_ci
35e41f4b71Sopenharmony_ci混淆开启后,默认使能对参数名和局部变量名的混淆,无需选项配置。顶层作用域名称混淆、属性名称的混淆、导出名称混淆、文件名混淆打开可能会导致运行时错误,这些混淆功能通过混淆配置选项来开启/关闭它们。
36e41f4b71Sopenharmony_ci
37e41f4b71Sopenharmony_ci创建一个新工程的时候,配置文件build-profile.json5中会自动生成以下内容:
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci```
40e41f4b71Sopenharmony_ci"arkOptions": {
41e41f4b71Sopenharmony_ci  "obfuscation": {
42e41f4b71Sopenharmony_ci    "ruleOptions": {
43e41f4b71Sopenharmony_ci      "enable": true,
44e41f4b71Sopenharmony_ci      "files": ["./obfuscation-rules.txt"],
45e41f4b71Sopenharmony_ci    }
46e41f4b71Sopenharmony_ci  }
47e41f4b71Sopenharmony_ci}
48e41f4b71Sopenharmony_ci```
49e41f4b71Sopenharmony_ci
50e41f4b71Sopenharmony_ci创建一个新的library的时候,还会额外生成consumerFiles属性:
51e41f4b71Sopenharmony_ci
52e41f4b71Sopenharmony_ci```
53e41f4b71Sopenharmony_ci"arkOptions": {
54e41f4b71Sopenharmony_ci  "obfuscation": {
55e41f4b71Sopenharmony_ci    "ruleOptions": {
56e41f4b71Sopenharmony_ci      "enable": true,
57e41f4b71Sopenharmony_ci      "files": ["./obfuscation-rules.txt"],
58e41f4b71Sopenharmony_ci    }
59e41f4b71Sopenharmony_ci    "consumerFiles": ["./consumer-rules.txt"]
60e41f4b71Sopenharmony_ci  }
61e41f4b71Sopenharmony_ci}
62e41f4b71Sopenharmony_ci```
63e41f4b71Sopenharmony_ci
64e41f4b71Sopenharmony_ci混淆功能被关闭希望重新开启混淆需要满足条件: 属性ruleOptions.enable的值为true。
65e41f4b71Sopenharmony_ci
66e41f4b71Sopenharmony_ci属性ruleOptions.files中指定的混淆配置文件会在构建HAP、HSP或HAR的时候生效。  
67e41f4b71Sopenharmony_ci属性consumerFiles中指定的混淆配置文件会在构建依赖这个library的模块时生效。这些混淆配置文件的内容还会被合并到HAR包中的obfuscation.txt文件。
68e41f4b71Sopenharmony_ci
69e41f4b71Sopenharmony_ci当构建HAP、HSP和HAR的时候,最终的混淆规则是当前构建模块的ruleOptions.files属性,依赖library的consumerFiles属性,以及依赖HAR包中的obfuscation.txt文件的合并。  
70e41f4b71Sopenharmony_ci如果构建的是HAR,HAR包中的obfuscation.txt是自身的consumerFiles属性, 依赖library的consumerFiles属性,以及依赖HAR包中的obfuscation.txt文件的合并。构建HAP、HSP不会生成obfuscation.txt。详细合并的策略可以查看[混淆规则合并策略](#混淆规则合并策略)。
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci**规则变更提醒**
73e41f4b71Sopenharmony_ci
74e41f4b71Sopenharmony_ci从DevEco Studio 5.0.3.600开始,新建工程默认关闭代码混淆功能,即`"enable": false`;混淆规则配置文件obfuscation-rules.txt中默认开启enable-property-obfuscation、-enable-toplevel-obfuscation、-enable-filename-obfuscation、-enable-export-obfuscation四项推荐的选项。这四项规则开启可能会引发应用运行时崩溃,建议阅读[排查指南](#如何排查功能异常)来修正应用功能。
75e41f4b71Sopenharmony_ci
76e41f4b71Sopenharmony_ci### 混淆规则配置文件
77e41f4b71Sopenharmony_ci
78e41f4b71Sopenharmony_ci在创建工程或library的时候,DevEco Studio会自动生成`obfuscation-rules.txt`和`consumer-rules.txt`文件。混淆规则可以写到这些文件中,或者其它自定义文件,然后将文件路径放到`ruleOptions.files`和`consumerFiles`中,如下面的例子所示。
79e41f4b71Sopenharmony_ci
80e41f4b71Sopenharmony_ci```
81e41f4b71Sopenharmony_ci"buildOption": {
82e41f4b71Sopenharmony_ci  "arkOptions": {
83e41f4b71Sopenharmony_ci    "obfuscation": {
84e41f4b71Sopenharmony_ci      "ruleOptions": {
85e41f4b71Sopenharmony_ci        "enable": true,
86e41f4b71Sopenharmony_ci        "files": ["./obfuscation-rules.txt", "./myrules.txt"], //myrules.txt放入配置文件build-profile.json5同级目录下
87e41f4b71Sopenharmony_ci      }
88e41f4b71Sopenharmony_ci      "consumerFiles": ["./consumer-rules.txt", "./my-consumer-rules.txt"]
89e41f4b71Sopenharmony_ci    }
90e41f4b71Sopenharmony_ci  }
91e41f4b71Sopenharmony_ci}
92e41f4b71Sopenharmony_ci```
93e41f4b71Sopenharmony_ci
94e41f4b71Sopenharmony_ci## 配置混淆规则
95e41f4b71Sopenharmony_ci
96e41f4b71Sopenharmony_ci混淆规则分为两种类型,一种是[混淆选项](#混淆选项),一种是[保留选项](#保留选项);前者是提供顶层作用域名称、属性名称、文件名称等多种混淆功能配置开关,后者是提供各种混淆功能的白名单配置能力。
97e41f4b71Sopenharmony_ci
98e41f4b71Sopenharmony_ci**注意**
99e41f4b71Sopenharmony_ci
100e41f4b71Sopenharmony_ci若修改应用混淆配置,新配置需要重新全量编译应用才能生效。
101e41f4b71Sopenharmony_ci
102e41f4b71Sopenharmony_ci### 混淆选项
103e41f4b71Sopenharmony_ci
104e41f4b71Sopenharmony_ci#### -disable-obfuscation
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ci关闭所有混淆。如果使用这个选项,那么构建出来的HAP、HSP或HAR将不会被混淆。
107e41f4b71Sopenharmony_ci
108e41f4b71Sopenharmony_ci#### -enable-property-obfuscation
109e41f4b71Sopenharmony_ci
110e41f4b71Sopenharmony_ci开启属性混淆。 如果使用这个选项,那么所有的属性名都会被混淆,除了下面场景:
111e41f4b71Sopenharmony_ci
112e41f4b71Sopenharmony_ci* 被`import/export`直接导入或导出的类、对象的属性名不会被混淆。例如下面例子中的属性名`data`不会被混淆。
113e41f4b71Sopenharmony_ci
114e41f4b71Sopenharmony_ci    ```
115e41f4b71Sopenharmony_ci    export class MyClass {
116e41f4b71Sopenharmony_ci       data: string;
117e41f4b71Sopenharmony_ci    }
118e41f4b71Sopenharmony_ci    ```
119e41f4b71Sopenharmony_ci
120e41f4b71Sopenharmony_ci* ArkUI组件中的属性名不会被混淆。例如下面例子中的`message`和`data`不会被混淆。
121e41f4b71Sopenharmony_ci
122e41f4b71Sopenharmony_ci    ```
123e41f4b71Sopenharmony_ci    @Component struct MyExample {
124e41f4b71Sopenharmony_ci        @State message: string = "hello";
125e41f4b71Sopenharmony_ci        data: number[] = [];
126e41f4b71Sopenharmony_ci        ...
127e41f4b71Sopenharmony_ci    }
128e41f4b71Sopenharmony_ci    ```
129e41f4b71Sopenharmony_ci
130e41f4b71Sopenharmony_ci* 被[保留选项](#保留选项)指定的属性名不会被混淆。
131e41f4b71Sopenharmony_ci* SDK API列表中的属性名不会被混淆。SDK API列表是构建时从SDK中自动提取出来的一个名称列表,其缓存文件为systemApiCache.json,路径为工程目录下build/default/cache/{...}/release/obfuscation132e41f4b71Sopenharmony_ci* 字符串字面量属性名不会被混淆。例如下面例子中的`"name"`和`"age"`不会被混淆。
133e41f4b71Sopenharmony_ci
134e41f4b71Sopenharmony_ci    ```
135e41f4b71Sopenharmony_ci    let person = {"name": "abc"};
136e41f4b71Sopenharmony_ci    person["age"] = 22;
137e41f4b71Sopenharmony_ci    ```
138e41f4b71Sopenharmony_ci
139e41f4b71Sopenharmony_ci    如果想混淆字符串字面量属性名,需要在该选项的基础上再使用`-enable-string-property-obfuscation`选项。例如
140e41f4b71Sopenharmony_ci
141e41f4b71Sopenharmony_ci    ```
142e41f4b71Sopenharmony_ci    -enable-property-obfuscation
143e41f4b71Sopenharmony_ci    -enable-string-property-obfuscation
144e41f4b71Sopenharmony_ci    ```
145e41f4b71Sopenharmony_ci
146e41f4b71Sopenharmony_ci    **注意**:  
147e41f4b71Sopenharmony_ci
148e41f4b71Sopenharmony_ci    **1.** 如果代码里面有字符串属性名包含特殊字符(除了`a-z, A-Z, 0-9, _`之外的字符),例如`let obj = {"\n": 123, "": 4, " ": 5}`,建议不要开启`-enable-string-property-obfuscation`选项,因为可能无法通过[保留选项](#保留选项)来指定保留这些名字。  
149e41f4b71Sopenharmony_ci    **2.** SDK API的属性白名单中不包含声明文件中使用的字符串常量值,例如示例中的字符串'ohos.want.action.home'未包含在属性白名单中
150e41f4b71Sopenharmony_ci
151e41f4b71Sopenharmony_ci    ```
152e41f4b71Sopenharmony_ci    // SDK API文件@ohos.app.ability.wantConstant片段:
153e41f4b71Sopenharmony_ci    export enum Params {
154e41f4b71Sopenharmony_ci      ACTION_HOME = 'ohos.want.action.home'
155e41f4b71Sopenharmony_ci    }
156e41f4b71Sopenharmony_ci    // 开发者源码示例:
157e41f4b71Sopenharmony_ci    let params = obj['ohos.want.action.home'];
158e41f4b71Sopenharmony_ci    ```
159e41f4b71Sopenharmony_ci
160e41f4b71Sopenharmony_ci    因此在开启了`-enable-string-property-obfuscation`选项时,如果想保留代码中使用的SDK API字符串常量的属性不被混淆,例如obj['ohos.want.action.home'], 那么需要使用keep选项保留。
161e41f4b71Sopenharmony_ci
162e41f4b71Sopenharmony_ci#### -enable-toplevel-obfuscation
163e41f4b71Sopenharmony_ci
164e41f4b71Sopenharmony_ci开启顶层作用域名称混淆。如果使用这个选项,那么所有的顶层作用域的名称都会被混淆,除了下面场景:
165e41f4b71Sopenharmony_ci
166e41f4b71Sopenharmony_ci* 被`import/export`的名称不会被混淆。
167e41f4b71Sopenharmony_ci* 当前文件找不到声明的名称不会被混淆。
168e41f4b71Sopenharmony_ci* 被[保留选项](#保留选项)指定的顶层作用域名称不会被混淆。
169e41f4b71Sopenharmony_ci* SDK API列表中的顶层作用域名称不会被混淆。
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci#### -enable-filename-obfuscation
172e41f4b71Sopenharmony_ci
173e41f4b71Sopenharmony_ci开启文件/文件夹名称混淆。如果使用这个选项,那么所有的文件/文件夹名称都会被混淆,例如:
174e41f4b71Sopenharmony_ci
175e41f4b71Sopenharmony_ci```
176e41f4b71Sopenharmony_ci// directory和filename都会混淆
177e41f4b71Sopenharmony_ciimport func from '../directory/filename';
178e41f4b71Sopenharmony_ciimport { foo } from '../directory/filename';
179e41f4b71Sopenharmony_ciconst module = import('../directory/filename');
180e41f4b71Sopenharmony_ci```
181e41f4b71Sopenharmony_ci
182e41f4b71Sopenharmony_ci除了下面场景:
183e41f4b71Sopenharmony_ci
184e41f4b71Sopenharmony_ci* oh-package.json5文件中'main'、'types'字段配置的文件/文件夹名称不会被混淆。
185e41f4b71Sopenharmony_ci* 模块内module.json5文件中'srcEntry'字段配置的文件/文件夹名称不会被混淆。
186e41f4b71Sopenharmony_ci* 被[-keep-file-name](#保留选项)指定的文件/文件夹名称不会被混淆。
187e41f4b71Sopenharmony_ci* 非ECMAScript模块引用方式(ECMAScript模块示例:`import {foo} from './filename'`)
188e41f4b71Sopenharmony_ci* 非路径引用方式,例如例子中的json5不会被混淆 `import module from 'json5'`  
189e41f4b71Sopenharmony_ci
190e41f4b71Sopenharmony_ci**注意**:  
191e41f4b71Sopenharmony_ci
192e41f4b71Sopenharmony_ci由于系统会在应用运行时加载某些指定的文件,针对这类文件,开发者需要手动在[-keep-file-name](#保留选项)选项中配置相应的白名单,防止指定文件被混淆,导致运行失败。
193e41f4b71Sopenharmony_ci上述需要手动配置白名单的情况,包括但不限于以下场景:  
194e41f4b71Sopenharmony_ci
195e41f4b71Sopenharmony_ci* 当模块中包含Ability组件时。用户需要将`src/main/module.json5`中,'abilities'字段下所有'srcEntry'对应的路径配置到白名单中。  
196e41f4b71Sopenharmony_ci* 当模块中包含Worker多线程服务时,用户需要将`build-profiles.json5`中,'buildOption'-'sourceOption'-'workers'字段下所有的路径配置到白名单中。
197e41f4b71Sopenharmony_ci
198e41f4b71Sopenharmony_ci**提醒**:
199e41f4b71Sopenharmony_ci
200e41f4b71Sopenharmony_ci编译入口、Ability组件、Worker多线程,这三种不能混淆的文件名在DevEco Studio 5.0.3.500版本已被自动收集进白名单中,无需再手动配置,其它不能混淆文件名的场景仍需开发者手动配置
201e41f4b71Sopenharmony_ci
202e41f4b71Sopenharmony_ci#### -enable-export-obfuscation
203e41f4b71Sopenharmony_ci
204e41f4b71Sopenharmony_ci开启直接导入或导出的类或对象的名称和属性名混淆。如果使用这个选项,那么模块中的直接导入或导出的名称都会被混淆,除了下面场景:
205e41f4b71Sopenharmony_ci
206e41f4b71Sopenharmony_ci* 远程HAR(真实路径在oh_modules中的包)中导出的类或对象的名称和属性名不会被混淆。
207e41f4b71Sopenharmony_ci* 被[保留选项](#保留选项)指定的名称与属性名不会被混淆。
208e41f4b71Sopenharmony_ci* SDK API列表中的名称不会被混淆。
209e41f4b71Sopenharmony_ci
210e41f4b71Sopenharmony_ci**注意**:
211e41f4b71Sopenharmony_ci
212e41f4b71Sopenharmony_ci1. 混淆导入或导出的类中属性名称需要同时开启`-enable-property-obfuscation`与`-enable-export-obfuscation`选项。  
213e41f4b71Sopenharmony_ci2. 编译HSP时,如果开启`-enable-export-obfuscation`选项,需要在模块中的混淆配置文件`obfuscation-rules.txt`中保留对外暴露的接口。
214e41f4b71Sopenharmony_ci3. HAP/HSP/HAR依赖HSP场景下,编译时如果开启`-enable-export-obfuscation`选项,需要在模块中的混淆配置文件`obfuscation-rules.txt`中保留HSP导入的接口。  
215e41f4b71Sopenharmony_ci
216e41f4b71Sopenharmony_ci    ```
217e41f4b71Sopenharmony_ci    // 代码示例(HSP中入口文件Index.ets):
218e41f4b71Sopenharmony_ci    export { add, customApiName } from './src/main/ets/utils/Calc'
219e41f4b71Sopenharmony_ci
220e41f4b71Sopenharmony_ci    // 保留接口名称配置示例:
221e41f4b71Sopenharmony_ci    // HSP以及依赖此HSP的模块中obfuscation-rules.txt文件配置: 
222e41f4b71Sopenharmony_ci    -keep-global-name
223e41f4b71Sopenharmony_ci    add
224e41f4b71Sopenharmony_ci    customApiName
225e41f4b71Sopenharmony_ci    ```
226e41f4b71Sopenharmony_ci
227e41f4b71Sopenharmony_ci#### -compact
228e41f4b71Sopenharmony_ci
229e41f4b71Sopenharmony_ci去除不必要的空格符和所有的换行符。如果使用这个选项,那么所有代码会被压缩到一行。
230e41f4b71Sopenharmony_ci
231e41f4b71Sopenharmony_ci**注意**:
232e41f4b71Sopenharmony_ci
233e41f4b71Sopenharmony_cirelease模式构建的应用栈信息仅包含代码行号,不包含列号,因此compact功能开启后无法依据报错栈中的行号定位到源码具体位置。
234e41f4b71Sopenharmony_ci
235e41f4b71Sopenharmony_ci#### -remove-log
236e41f4b71Sopenharmony_ci
237e41f4b71Sopenharmony_ci删除以下场景中对 console.*语句的调用,要求console.*语句返回值未被调用。
238e41f4b71Sopenharmony_ci
239e41f4b71Sopenharmony_ci1. 文件顶层的调用
240e41f4b71Sopenharmony_ci2. 代码块Block中的调用
241e41f4b71Sopenharmony_ci3. 模块Module中的调用
242e41f4b71Sopenharmony_ci4. switch语句中的调用
243e41f4b71Sopenharmony_ci
244e41f4b71Sopenharmony_ci#### -print-namecache *filepath*
245e41f4b71Sopenharmony_ci
246e41f4b71Sopenharmony_ci将名称缓存保存到指定的文件路径。名称缓存包含名称混淆前后的映射。  
247e41f4b71Sopenharmony_ci
248e41f4b71Sopenharmony_ci**注意**:
249e41f4b71Sopenharmony_ci
250e41f4b71Sopenharmony_ci每次全量构建工程时都会生成新的namecache.json文件,因此您每次发布新版本时都要注意保存一个该文件的副本。
251e41f4b71Sopenharmony_ci
252e41f4b71Sopenharmony_ci#### -apply-namecache *filepath*
253e41f4b71Sopenharmony_ci
254e41f4b71Sopenharmony_ci复用指定的名称缓存文件。名字将会被混淆成缓存映射对应的名字,如果没有对应,将会被混淆成新的随机段名字。
255e41f4b71Sopenharmony_ci该选项应该在增量编译场景中被使用。
256e41f4b71Sopenharmony_ci
257e41f4b71Sopenharmony_ci默认情况下,DevEco Studio会在临时的缓存目录中保存缓存文件,并且在增量编译场景中自动应用该缓存文件。  
258e41f4b71Sopenharmony_ci缓存目录:build/default/cache/{...}/release/obfuscation
259e41f4b71Sopenharmony_ci
260e41f4b71Sopenharmony_ci#### -remove-comments
261e41f4b71Sopenharmony_ci
262e41f4b71Sopenharmony_ci删除编译生成的声明文件中的JsDoc注释。  
263e41f4b71Sopenharmony_ci
264e41f4b71Sopenharmony_ci**注意**:  
265e41f4b71Sopenharmony_ci
266e41f4b71Sopenharmony_ci编译生成的源码文件中的注释默认会被全部删除,不支持配置保留。  
267e41f4b71Sopenharmony_ci可通过`keep-comments`配置来保留编译生成的声明文件中的JsDoc注释。
268e41f4b71Sopenharmony_ci
269e41f4b71Sopenharmony_ci#### -print-kept-names *filepath*
270e41f4b71Sopenharmony_ci
271e41f4b71Sopenharmony_ci该选项支持输出未混淆名单和全量白名单。其中,*filepath*为可选参数。
272e41f4b71Sopenharmony_ci
273e41f4b71Sopenharmony_ci当*filepath*参数缺省时,未混淆名单(keptNames.json)和全量白名单(whitelist.json)默认输出到缓存路径`build/default/cache/{...}/release/obfuscation`中。
274e41f4b71Sopenharmony_ci
275e41f4b71Sopenharmony_ci当*filepath*配置参数时,未混淆名单还会输出到该参数指定的路径中。其中,*filepath*仅支持相对路径,相对路径的起始位置为混淆配置文件的当前目录。*filepath*参数中的文件名请以`.json`为后缀。
276e41f4b71Sopenharmony_ci
277e41f4b71Sopenharmony_ci全量白名单(whitelist.json)包含本次模块编译流程中收集到的全部白名单,分为以下七种:
278e41f4b71Sopenharmony_ci
279e41f4b71Sopenharmony_ci(1)'sdk':表示系统api。
280e41f4b71Sopenharmony_ci
281e41f4b71Sopenharmony_ci(2)'lang':表示语言中的关键字。
282e41f4b71Sopenharmony_ci
283e41f4b71Sopenharmony_ci(3)'conf':表示用户配置的保留选项中的白名单。
284e41f4b71Sopenharmony_ci
285e41f4b71Sopenharmony_ci(4)'struct':表示ArkUI的struct中的属性。
286e41f4b71Sopenharmony_ci
287e41f4b71Sopenharmony_ci(5)'exported':表示被导出的名称及其属性。
288e41f4b71Sopenharmony_ci
289e41f4b71Sopenharmony_ci(6)'strProp': 表示字符串属性。
290e41f4b71Sopenharmony_ci
291e41f4b71Sopenharmony_ci(7)'enum':表示enum中的成员。
292e41f4b71Sopenharmony_ci
293e41f4b71Sopenharmony_ci未混淆名单(keptNames.json)中包含未混淆的名称及未混淆的原因。其中,未混淆原因有以下七种:与sdk白名单重名、与语言白名单重名、与用户配置白名单重名、与struct白名单重名、与导出白名单重名、与字符串属性白名单重名(未开启字符串属性混淆的情况下)以及与enum白名单重名。
294e41f4b71Sopenharmony_ci
295e41f4b71Sopenharmony_ci**注意**:
296e41f4b71Sopenharmony_ci
297e41f4b71Sopenharmony_ci1.在编译har模块且开启属性混淆的情况下,'enum'白名单将收集enum中的成员名称。
298e41f4b71Sopenharmony_ci
299e41f4b71Sopenharmony_ci例如:
300e41f4b71Sopenharmony_ci
301e41f4b71Sopenharmony_ci```
302e41f4b71Sopenharmony_cienum Test {
303e41f4b71Sopenharmony_ci  member1,
304e41f4b71Sopenharmony_ci  member2
305e41f4b71Sopenharmony_ci}
306e41f4b71Sopenharmony_ci```
307e41f4b71Sopenharmony_ci
308e41f4b71Sopenharmony_cienum白名单内容为['member1', 'member2']。这是由于历史版本的har模块的编译中间产物为js文件,在js文件中enum类型会转换为一个立即执行函数,而enum成员会被转化为一个字符串属性和一个字符串常量。因此,为了保证开启属性混淆的情况下功能正常,需要将enum成员名称收集为白名单。在编译新版字节码har模块时,此特性仍然被保留。
309e41f4b71Sopenharmony_ci
310e41f4b71Sopenharmony_ci2.在编译hap/hsp/字节码har模块且开启属性混淆的情况下,当enum的成员被初始化时,'enum'白名单收集初始化表达式中包含的变量名称。
311e41f4b71Sopenharmony_ci
312e41f4b71Sopenharmony_ci例如:
313e41f4b71Sopenharmony_ci
314e41f4b71Sopenharmony_ci```
315e41f4b71Sopenharmony_cilet outdoor = 1;
316e41f4b71Sopenharmony_cienum Test {
317e41f4b71Sopenharmony_ci  member1,
318e41f4b71Sopenharmony_ci  member2 = outdoor + member1 + 2
319e41f4b71Sopenharmony_ci}
320e41f4b71Sopenharmony_ci```
321e41f4b71Sopenharmony_ci
322e41f4b71Sopenharmony_ci其中,编译hap/hsp模块的情况下,enum白名单内容为['outdoor', 'member1'];编译字节码har模块的情况下,enum白名单内容为['outdoor', 'member1', 'member2']。
323e41f4b71Sopenharmony_ci
324e41f4b71Sopenharmony_ci### 保留选项
325e41f4b71Sopenharmony_ci
326e41f4b71Sopenharmony_ci#### -keep-property-name *[,identifiers,...]*
327e41f4b71Sopenharmony_ci
328e41f4b71Sopenharmony_ci指定想保留的属性名,支持使用名称类通配符。例如下面的例子:
329e41f4b71Sopenharmony_ci
330e41f4b71Sopenharmony_ci```
331e41f4b71Sopenharmony_ci-keep-property-name
332e41f4b71Sopenharmony_ciage
333e41f4b71Sopenharmony_cifirstName
334e41f4b71Sopenharmony_cilastName
335e41f4b71Sopenharmony_ci```
336e41f4b71Sopenharmony_ci
337e41f4b71Sopenharmony_ci**注意**:
338e41f4b71Sopenharmony_ci
339e41f4b71Sopenharmony_ci该选项在开启`-enable-property-obfuscation`时生效
340e41f4b71Sopenharmony_ci
341e41f4b71Sopenharmony_ci**哪些属性名应该被保留?**
342e41f4b71Sopenharmony_ci
343e41f4b71Sopenharmony_ci为了保障混淆的正确性,建议保留所有不通过点语法访问的属性。
344e41f4b71Sopenharmony_ci
345e41f4b71Sopenharmony_ci例子:
346e41f4b71Sopenharmony_ci
347e41f4b71Sopenharmony_ci```
348e41f4b71Sopenharmony_civar obj = {x0: 0, x1: 0, x2: 0};
349e41f4b71Sopenharmony_cifor (var i = 0; i <= 2; i++) {
350e41f4b71Sopenharmony_ci    console.info(obj['x' + i]);  // x0, x1, x2 应该被保留
351e41f4b71Sopenharmony_ci}
352e41f4b71Sopenharmony_ci
353e41f4b71Sopenharmony_ciObject.defineProperty(obj, 'y', {});  // y 应该被保留
354e41f4b71Sopenharmony_ciconsole.info(obj.y);
355e41f4b71Sopenharmony_ci
356e41f4b71Sopenharmony_ciobj.s = 0;
357e41f4b71Sopenharmony_cilet key = 's';
358e41f4b71Sopenharmony_ciconsole.info(obj[key]);        // s 应该被保留
359e41f4b71Sopenharmony_ci
360e41f4b71Sopenharmony_ciobj.u = 0;
361e41f4b71Sopenharmony_ciconsole.info(obj.u);           // u 可以被正确地混淆
362e41f4b71Sopenharmony_ci
363e41f4b71Sopenharmony_ciobj.t = 0;
364e41f4b71Sopenharmony_ciconsole.info(obj['t']);        // 在开启字符串字面量属性名混淆时t和't'会被正确地混淆,但是建议保留
365e41f4b71Sopenharmony_ci
366e41f4b71Sopenharmony_ciobj['v'] = 0;
367e41f4b71Sopenharmony_ciconsole.info(obj['v']);        // 在开启字符串字面量属性名混淆时'v'会被正确地混淆,但是建议保留
368e41f4b71Sopenharmony_ci```
369e41f4b71Sopenharmony_ci
370e41f4b71Sopenharmony_ci对于间接导出的场景,例如`export MyClass`和`let a = MyClass; export {a};`,如果不想混淆它们的属性名,那么需要使用[保留选项](#保留选项)来保留这些属性名。另外,对于直接导出的类或对象的属性的属性名,例如下面例子中的`name`和`age`, 如果不想混淆它们,那么也需要使用[保留选项](#保留选项)来保留这些属性名。
371e41f4b71Sopenharmony_ci
372e41f4b71Sopenharmony_ci```
373e41f4b71Sopenharmony_ciexport class MyClass {
374e41f4b71Sopenharmony_ci    person = {name: "123", age: 100};
375e41f4b71Sopenharmony_ci}
376e41f4b71Sopenharmony_ci```
377e41f4b71Sopenharmony_ci
378e41f4b71Sopenharmony_ciso库的API(例如示例中的foo),如果要在ArkTS/TS/JS文件中使用需手动保留API名称。
379e41f4b71Sopenharmony_ci
380e41f4b71Sopenharmony_ci```
381e41f4b71Sopenharmony_ciimport testNapi from 'library.so'
382e41f4b71Sopenharmony_citestNapi.foo() // foo需要保留,示例如:-keep-property-name foo
383e41f4b71Sopenharmony_ci```
384e41f4b71Sopenharmony_ci
385e41f4b71Sopenharmony_ci使用到的json文件中的字段,需要手动保留。
386e41f4b71Sopenharmony_ci
387e41f4b71Sopenharmony_ci```
388e41f4b71Sopenharmony_ciconst jsonData = ('./1.json')
389e41f4b71Sopenharmony_cilet jsonStr = JSON.parse(jsonData)
390e41f4b71Sopenharmony_cilet jsonObj = jsonStr.jsonProperty  // jsonProperty 需要被保留
391e41f4b71Sopenharmony_ci```
392e41f4b71Sopenharmony_ci
393e41f4b71Sopenharmony_ci使用到的数据库相关的字段,需要手动保留。
394e41f4b71Sopenharmony_ci
395e41f4b71Sopenharmony_ci```
396e41f4b71Sopenharmony_ciconst dataToInsert = {  
397e41f4b71Sopenharmony_ci  value1: 'example1',   // value1 需要被保留
398e41f4b71Sopenharmony_ci};
399e41f4b71Sopenharmony_ci```
400e41f4b71Sopenharmony_ci
401e41f4b71Sopenharmony_ci源码中自定义装饰器修饰了成员变量、成员方法、参数,同时其源码编译的中间产物为js文件时(如编译release源码HAR或者源码包含@ts-ignore、@ts-nocheck),这些装饰器所在的成员变量/成员方法名称需要被保留。这是由于ts高级语法特性转换为js标准语法时,将上述装饰器所在的成员变量/成员方法名称硬编码为字符串常量。
402e41f4b71Sopenharmony_ci
403e41f4b71Sopenharmony_ci示例:
404e41f4b71Sopenharmony_ci
405e41f4b71Sopenharmony_ci```
406e41f4b71Sopenharmony_ciclass A {
407e41f4b71Sopenharmony_ci  // 1.成员变量装饰器
408e41f4b71Sopenharmony_ci  @CustomDecoarter
409e41f4b71Sopenharmony_ci  propetyName: string = ""   // propetyName 需要被保留
410e41f4b71Sopenharmony_ci  // 2.成员方法装饰器
411e41f4b71Sopenharmony_ci  @MethodDecoarter
412e41f4b71Sopenharmony_ci  methodName1(){} // methodName1 需要被保留
413e41f4b71Sopenharmony_ci  // 3.方法参数装饰器
414e41f4b71Sopenharmony_ci  methodName2(@ParamDecorator param: string): void { // methodName2 需要被保留
415e41f4b71Sopenharmony_ci  }
416e41f4b71Sopenharmony_ci}
417e41f4b71Sopenharmony_ci```
418e41f4b71Sopenharmony_ci
419e41f4b71Sopenharmony_ci#### -keep-global-name *[,identifiers,...]*
420e41f4b71Sopenharmony_ci
421e41f4b71Sopenharmony_ci指定要保留的顶层作用域的名称,支持使用名称类通配符。例如,
422e41f4b71Sopenharmony_ci
423e41f4b71Sopenharmony_ci```
424e41f4b71Sopenharmony_ci-keep-global-name
425e41f4b71Sopenharmony_ciPerson
426e41f4b71Sopenharmony_ciprintPersonName
427e41f4b71Sopenharmony_ci```
428e41f4b71Sopenharmony_ci
429e41f4b71Sopenharmony_cinamespace中导出的名称也可以通过`-keep-global-name`保留。
430e41f4b71Sopenharmony_ci
431e41f4b71Sopenharmony_ci```
432e41f4b71Sopenharmony_ciexport namespace Ns {
433e41f4b71Sopenharmony_ci  export const age = 18; // -keep-global-name age 保留变量age
434e41f4b71Sopenharmony_ci  export function myFunc () {}; // -keep-global-name myFunc 保留函数myFunc
435e41f4b71Sopenharmony_ci}
436e41f4b71Sopenharmony_ci```
437e41f4b71Sopenharmony_ci
438e41f4b71Sopenharmony_ci**哪些顶层作用域的名称应该被保留?**
439e41f4b71Sopenharmony_ci
440e41f4b71Sopenharmony_ci在JavaScript中全局变量是`globalThis`的属性。如果在代码中使用`globalThis`去访问全局变量,那么该变量名应该被保留。
441e41f4b71Sopenharmony_ci
442e41f4b71Sopenharmony_ci示例:
443e41f4b71Sopenharmony_ci
444e41f4b71Sopenharmony_ci```
445e41f4b71Sopenharmony_civar a = 0;
446e41f4b71Sopenharmony_ciconsole.info(globalThis.a);  // a 应该被保留
447e41f4b71Sopenharmony_ci
448e41f4b71Sopenharmony_cifunction foo(){}
449e41f4b71Sopenharmony_ciglobalThis.foo();           // foo 应该被保留
450e41f4b71Sopenharmony_ci
451e41f4b71Sopenharmony_civar c = 0;
452e41f4b71Sopenharmony_ciconsole.info(c);             // c 可以被正确地混淆
453e41f4b71Sopenharmony_ci
454e41f4b71Sopenharmony_cifunction bar(){}
455e41f4b71Sopenharmony_cibar();                      // bar 可以被正确地混淆
456e41f4b71Sopenharmony_ci
457e41f4b71Sopenharmony_ciclass MyClass {}
458e41f4b71Sopenharmony_cilet d = new MyClass();      // MyClass 可以被正确地混淆
459e41f4b71Sopenharmony_ci```
460e41f4b71Sopenharmony_ci
461e41f4b71Sopenharmony_ci当以命名导入的方式导入 so 库的 API时,若同时开启`-enable-toplevel-obfuscation`和`-enable-export-obfuscation`选项,需要手动保留 API 的名称。
462e41f4b71Sopenharmony_ci
463e41f4b71Sopenharmony_ci```
464e41f4b71Sopenharmony_ciimport { testNapi, testNapi1 as myNapi } from 'library.so' // testNapi 和 testNapi1 应该被保留
465e41f4b71Sopenharmony_ci```
466e41f4b71Sopenharmony_ci
467e41f4b71Sopenharmony_ci#### -keep-file-name *[,identifiers,...]*
468e41f4b71Sopenharmony_ci
469e41f4b71Sopenharmony_ci指定要保留的文件/文件夹的名称(不需要写文件后缀),支持使用名称类通配符。例如,
470e41f4b71Sopenharmony_ci
471e41f4b71Sopenharmony_ci```
472e41f4b71Sopenharmony_ci-keep-file-name
473e41f4b71Sopenharmony_ciindex
474e41f4b71Sopenharmony_cientry
475e41f4b71Sopenharmony_ci```
476e41f4b71Sopenharmony_ci
477e41f4b71Sopenharmony_ci**哪些文件名应该被保留?**
478e41f4b71Sopenharmony_ci
479e41f4b71Sopenharmony_ci```
480e41f4b71Sopenharmony_ciconst module1 = require('./file1')   // ArkTS不支持CommonJS语法,这种路径引用应该被保留
481e41f4b71Sopenharmony_ciconst moduleName = './file2'
482e41f4b71Sopenharmony_ciconst module2 = import(moduleName)    // 动态引用方式无法识别moduleName是否是路径,应该被保留
483e41f4b71Sopenharmony_ci```
484e41f4b71Sopenharmony_ci
485e41f4b71Sopenharmony_ci#### -keep-comments *[,identifiers,...]*
486e41f4b71Sopenharmony_ci
487e41f4b71Sopenharmony_ci保留编译生成的声明文件中class, function, namespace, enum, struct, interface, module, type及属性上方的JsDoc注释,支持使用名称类通配符。例如想保留声明文件中Human类上方的JsDoc注释,可进行以下配置:
488e41f4b71Sopenharmony_ci
489e41f4b71Sopenharmony_ci```
490e41f4b71Sopenharmony_ci-keep-comments
491e41f4b71Sopenharmony_ciHuman
492e41f4b71Sopenharmony_ci```
493e41f4b71Sopenharmony_ci
494e41f4b71Sopenharmony_ci**注意**:
495e41f4b71Sopenharmony_ci
496e41f4b71Sopenharmony_ci1. 该选项在开启`-remove-comments`时生效
497e41f4b71Sopenharmony_ci2. 当编译生成的声明文件中class, function, namespace, enum, struct, interface, module, type及属性的名称被混淆时,该元素上方的JsDoc注释无法通过`-keep-comments`保留。例如当在`-keep-comments`中配置了exportClass时,如果exportClass类名被混淆,其JsDoc注释无法被保留:
498e41f4b71Sopenharmony_ci
499e41f4b71Sopenharmony_ci```
500e41f4b71Sopenharmony_ci/*
501e41f4b71Sopenharmony_ci * @class exportClass
502e41f4b71Sopenharmony_ci */
503e41f4b71Sopenharmony_ciexport class exportClass {}
504e41f4b71Sopenharmony_ci```
505e41f4b71Sopenharmony_ci
506e41f4b71Sopenharmony_ci#### -keep-dts *filepath*
507e41f4b71Sopenharmony_ci
508e41f4b71Sopenharmony_ci保留指定绝对路径的`.d.ts`文件中的名称。这里的文件路径也可以是一个目录,这种情况下目录中所有`.d.ts`文件中的名称都会被保留。
509e41f4b71Sopenharmony_ci
510e41f4b71Sopenharmony_ci#### -keep *filepath*
511e41f4b71Sopenharmony_ci
512e41f4b71Sopenharmony_ci保留指定相对路径中的所有名称(例如变量名、类名、属性名等)不被混淆。这个路径可以是文件与文件夹,若是文件夹,则文件夹下的文件及子文件夹中文件都不混淆。  
513e41f4b71Sopenharmony_ci路径仅支持相对路径,`./`与`../`为相对于混淆配置文件所在目录,支持使用路径类通配符。
514e41f4b71Sopenharmony_ci
515e41f4b71Sopenharmony_ci```
516e41f4b71Sopenharmony_ci-keep
517e41f4b71Sopenharmony_ci./src/main/ets/fileName.ts   // fileName.ts中的名称不混淆
518e41f4b71Sopenharmony_ci../folder                    // folder目录下文件及子文件夹中的名称都不混淆
519e41f4b71Sopenharmony_ci../oh_modules/json5          // 引用的三方库json5里所有文件中的名称都不混淆
520e41f4b71Sopenharmony_ci```
521e41f4b71Sopenharmony_ci
522e41f4b71Sopenharmony_ci**注意**:
523e41f4b71Sopenharmony_ci
524e41f4b71Sopenharmony_ci1. 被`-keep filepath`所保留的文件,其依赖链路上的文件中导出名称及其属性都会被保留。
525e41f4b71Sopenharmony_ci2. 该功能不影响文件名混淆`-enable-filename-obfuscation`的功能。
526e41f4b71Sopenharmony_ci
527e41f4b71Sopenharmony_ci#### 保留选项支持的通配符
528e41f4b71Sopenharmony_ci
529e41f4b71Sopenharmony_ci##### 名称类通配符
530e41f4b71Sopenharmony_ci
531e41f4b71Sopenharmony_ci名称类通配符使用方式如下:
532e41f4b71Sopenharmony_ci
533e41f4b71Sopenharmony_ci| 通配符 | 含义                   | 示例                                       |
534e41f4b71Sopenharmony_ci| ------ | ---------------------- | ------------------------------------------ |
535e41f4b71Sopenharmony_ci| ?      | 匹配任意单个字符       | "AB?"能匹配"ABC"等,但不能匹配"AB"         |
536e41f4b71Sopenharmony_ci| \*     | 匹配任意数量的任意字符 | "\*AB\*"能匹配"AB"、"aABb"、"cAB"、"ABc"等 |
537e41f4b71Sopenharmony_ci
538e41f4b71Sopenharmony_ci**使用示例**:
539e41f4b71Sopenharmony_ci
540e41f4b71Sopenharmony_ci保留所有以a开头的属性名称:
541e41f4b71Sopenharmony_ci
542e41f4b71Sopenharmony_ci```
543e41f4b71Sopenharmony_ci-keep-property-name
544e41f4b71Sopenharmony_cia*
545e41f4b71Sopenharmony_ci```
546e41f4b71Sopenharmony_ci
547e41f4b71Sopenharmony_ci保留所有单个字符的属性名称:
548e41f4b71Sopenharmony_ci
549e41f4b71Sopenharmony_ci```
550e41f4b71Sopenharmony_ci-keep-property-name
551e41f4b71Sopenharmony_ci?
552e41f4b71Sopenharmony_ci```
553e41f4b71Sopenharmony_ci
554e41f4b71Sopenharmony_ci保留所有属性名称:
555e41f4b71Sopenharmony_ci
556e41f4b71Sopenharmony_ci```
557e41f4b71Sopenharmony_ci-keep-property-name
558e41f4b71Sopenharmony_ci*
559e41f4b71Sopenharmony_ci```
560e41f4b71Sopenharmony_ci
561e41f4b71Sopenharmony_ci##### 路径类通配符
562e41f4b71Sopenharmony_ci
563e41f4b71Sopenharmony_ci路径类通配符使用方式如下:
564e41f4b71Sopenharmony_ci
565e41f4b71Sopenharmony_ci| 通配符 | 含义                                                                     | 示例                                              |
566e41f4b71Sopenharmony_ci| ------ | ------------------------------------------------------------------------ | ------------------------------------------------- |
567e41f4b71Sopenharmony_ci| ?     | 匹配任意单个字符,除了路径分隔符`/`                                      | "../a?"能匹配"../ab"等,但不能匹配"../a/"         |
568e41f4b71Sopenharmony_ci| \*      | 匹配任意数量的任意字符,除了路径分隔符`/`                                | "../a*/c"能匹配"../ab/c",但不能匹配"../ab/d/s/c" |
569e41f4b71Sopenharmony_ci| \*\*   | 匹配任意数量的任意字符                                                   | "../a**/c"能匹配"../ab/c",也能匹配"../ab/d/s/c"  |
570e41f4b71Sopenharmony_ci| !      | 表示非,只能写在某个路径最前端,用来排除用户配置的白名单中已有的某种情况 | "!../a/b/c.ets"表示除"../a/b/c.ets"以外           |
571e41f4b71Sopenharmony_ci
572e41f4b71Sopenharmony_ci**使用示例**:
573e41f4b71Sopenharmony_ci
574e41f4b71Sopenharmony_ci表示路径../a/b/中所有文件夹(不包含子文件夹)中的c.ets文件不会被混淆:
575e41f4b71Sopenharmony_ci
576e41f4b71Sopenharmony_ci```
577e41f4b71Sopenharmony_ci-keep
578e41f4b71Sopenharmony_ci../a/b/*/c.ets
579e41f4b71Sopenharmony_ci```
580e41f4b71Sopenharmony_ci
581e41f4b71Sopenharmony_ci表示路径../a/b/中所有文件夹(包含子文件夹)中的c.ets文件不会被混淆:
582e41f4b71Sopenharmony_ci
583e41f4b71Sopenharmony_ci```
584e41f4b71Sopenharmony_ci-keep
585e41f4b71Sopenharmony_ci../a/b/**/c.ets
586e41f4b71Sopenharmony_ci```
587e41f4b71Sopenharmony_ci
588e41f4b71Sopenharmony_ci表示路径../a/b/中,除了c.ets文件以外的其它文件都不会被混淆。其中,`!`不可单独使用,只能用来排除白名单中已有的情况:
589e41f4b71Sopenharmony_ci
590e41f4b71Sopenharmony_ci```
591e41f4b71Sopenharmony_ci-keep
592e41f4b71Sopenharmony_ci../a/b/
593e41f4b71Sopenharmony_ci!../a/b/c.ets
594e41f4b71Sopenharmony_ci```
595e41f4b71Sopenharmony_ci
596e41f4b71Sopenharmony_ci表示路径../a/中的所有文件(不包含子文件夹)不会被混淆:
597e41f4b71Sopenharmony_ci
598e41f4b71Sopenharmony_ci```
599e41f4b71Sopenharmony_ci-keep
600e41f4b71Sopenharmony_ci../a/*
601e41f4b71Sopenharmony_ci```
602e41f4b71Sopenharmony_ci
603e41f4b71Sopenharmony_ci表示路径../a/下的所有文件夹(包含子文件夹)中的所有文件不会被混淆:
604e41f4b71Sopenharmony_ci
605e41f4b71Sopenharmony_ci```
606e41f4b71Sopenharmony_ci-keep
607e41f4b71Sopenharmony_ci../a/**
608e41f4b71Sopenharmony_ci```
609e41f4b71Sopenharmony_ci
610e41f4b71Sopenharmony_ci表示模块内的所有文件不会被混淆:
611e41f4b71Sopenharmony_ci
612e41f4b71Sopenharmony_ci```
613e41f4b71Sopenharmony_ci-keep
614e41f4b71Sopenharmony_ci./**
615e41f4b71Sopenharmony_ci```
616e41f4b71Sopenharmony_ci
617e41f4b71Sopenharmony_ci**注意**:
618e41f4b71Sopenharmony_ci
619e41f4b71Sopenharmony_ci(1)以上选项,不支持配置通配符`*`、`?`、`!`作其它含义使用。
620e41f4b71Sopenharmony_ci例如:
621e41f4b71Sopenharmony_ci
622e41f4b71Sopenharmony_ci```
623e41f4b71Sopenharmony_ciclass A {
624e41f4b71Sopenharmony_ci  '*'= 1
625e41f4b71Sopenharmony_ci}
626e41f4b71Sopenharmony_ci
627e41f4b71Sopenharmony_ci-keep-property-name
628e41f4b71Sopenharmony_ci*
629e41f4b71Sopenharmony_ci```
630e41f4b71Sopenharmony_ci
631e41f4b71Sopenharmony_ci此时`*`表示匹配任意数量的任意字符,配置效果为所有属性名称都不混淆,而不是只有`*`属性不被混淆。
632e41f4b71Sopenharmony_ci
633e41f4b71Sopenharmony_ci(2)-keep选项中只允许使用`/`路径格式,不支持`\`或`\\`。
634e41f4b71Sopenharmony_ci
635e41f4b71Sopenharmony_ci### 注释
636e41f4b71Sopenharmony_ci
637e41f4b71Sopenharmony_ci可以使用`#`在混淆规则文件中进行注释。每行以`#`开头的文本会被当做是注释,例如下面的例子:
638e41f4b71Sopenharmony_ci
639e41f4b71Sopenharmony_ci```
640e41f4b71Sopenharmony_ci# white list for MainAbility.ets
641e41f4b71Sopenharmony_ci-keep-global-name
642e41f4b71Sopenharmony_ciMyComponent
643e41f4b71Sopenharmony_ciGlobalFunction
644e41f4b71Sopenharmony_ci
645e41f4b71Sopenharmony_ci-keep-property-name # white list for dynamic property names
646e41f4b71Sopenharmony_cifirstName
647e41f4b71Sopenharmony_cilastName
648e41f4b71Sopenharmony_ciage
649e41f4b71Sopenharmony_ci```
650e41f4b71Sopenharmony_ci
651e41f4b71Sopenharmony_ci构建HAR时,注释不会被合并到最后的`obfuscation.txt`文件中。
652e41f4b71Sopenharmony_ci
653e41f4b71Sopenharmony_ci### 混淆规则合并策略
654e41f4b71Sopenharmony_ci
655e41f4b71Sopenharmony_ci一个工程中经常会有许多混淆规则文件,这些文件来自于:
656e41f4b71Sopenharmony_ci
657e41f4b71Sopenharmony_ci* 主工程的`ruleOptions.files` (这里主工程指的是正在构建的工程)
658e41f4b71Sopenharmony_ci* 本地依赖的library中的`consumerFiles`选项中指定的文件
659e41f4b71Sopenharmony_ci* 远程依赖的HAR包中的`obfuscation.txt`文件
660e41f4b71Sopenharmony_ci
661e41f4b71Sopenharmony_ci当构建主工程的时候,这些文件中的混淆规则会按照下面的合并策略(伪代码)进行合并:
662e41f4b71Sopenharmony_ci
663e41f4b71Sopenharmony_ci```
664e41f4b71Sopenharmony_cilet `listRules` 表示上面提到的所有混淆规则文件的列表
665e41f4b71Sopenharmony_cilet finalRule = {
666e41f4b71Sopenharmony_ci    disableObfuscation: false,
667e41f4b71Sopenharmony_ci    enablePropertyObfuscation: false,
668e41f4b71Sopenharmony_ci    enableToplevelObfuscation: false,
669e41f4b71Sopenharmony_ci    compact: false,
670e41f4b71Sopenharmony_ci    removeLog: false,
671e41f4b71Sopenharmony_ci    keepPropertyName: [],
672e41f4b71Sopenharmony_ci    keepGlobalName: [],
673e41f4b71Sopenharmony_ci    keepDts: [],
674e41f4b71Sopenharmony_ci    printNamecache: string,
675e41f4b71Sopenharmony_ci    applyNamecache: string
676e41f4b71Sopenharmony_ci}
677e41f4b71Sopenharmony_cifor each file in `listRules`:
678e41f4b71Sopenharmony_ci    for each option in file:
679e41f4b71Sopenharmony_ci        switch(option) {
680e41f4b71Sopenharmony_ci            case -disable-obfuscation:
681e41f4b71Sopenharmony_ci                finalRule.disableObfuscation = true;
682e41f4b71Sopenharmony_ci                continue;
683e41f4b71Sopenharmony_ci            case -enable-property-obfuscation:
684e41f4b71Sopenharmony_ci                finalRule.enablePropertyObfuscation = true;
685e41f4b71Sopenharmony_ci                continue;
686e41f4b71Sopenharmony_ci            case -enable-toplevel-obfuscation:
687e41f4b71Sopenharmony_ci                finalRule.enableToplevelObfuscation = true;
688e41f4b71Sopenharmony_ci                continue;
689e41f4b71Sopenharmony_ci            case -compact:
690e41f4b71Sopenharmony_ci                finalRule.compact = true;
691e41f4b71Sopenharmony_ci                continue;
692e41f4b71Sopenharmony_ci            case -remove-log:
693e41f4b71Sopenharmony_ci                finalRule.removeLog = true;
694e41f4b71Sopenharmony_ci                continue;
695e41f4b71Sopenharmony_ci            case -print-namecache:
696e41f4b71Sopenharmony_ci                finalRule.printNamecache = #{指定的路径名};
697e41f4b71Sopenharmony_ci                continue;
698e41f4b71Sopenharmony_ci            case -apply-namecache:
699e41f4b71Sopenharmony_ci                finalRule.applyNamecache = #{指定的路径名};
700e41f4b71Sopenharmony_ci                continue;
701e41f4b71Sopenharmony_ci            case -keep-property-name:
702e41f4b71Sopenharmony_ci                finalRule.keepPropertyName.push(#{指定的名称});
703e41f4b71Sopenharmony_ci                continue;
704e41f4b71Sopenharmony_ci            case -keep-global-name:
705e41f4b71Sopenharmony_ci                finalRule.keepGlobalName.push(#{指定的名称});
706e41f4b71Sopenharmony_ci                continue;
707e41f4b71Sopenharmony_ci            case -keep-dts:
708e41f4b71Sopenharmony_ci                finalRule.keepDts.push(#{指定的路径});
709e41f4b71Sopenharmony_ci                continue;
710e41f4b71Sopenharmony_ci        }
711e41f4b71Sopenharmony_ci    end-for
712e41f4b71Sopenharmony_ciend-for
713e41f4b71Sopenharmony_ci```
714e41f4b71Sopenharmony_ci
715e41f4b71Sopenharmony_ci最后使用的混淆规则来自于对象`finalRule`。
716e41f4b71Sopenharmony_ci
717e41f4b71Sopenharmony_ci如果构建的是HAR,那么最终的`obfuscation.txt`文件内容来自于自身和本地依赖的library的`consumerFiles`选项,以及依赖的HAR的`obfuscation.txt`文件的合并。
718e41f4b71Sopenharmony_ci
719e41f4b71Sopenharmony_ci当`consumerFiles`指定的混淆配置文件中包含以下混淆规则时,这些混淆规则会被合并到HAR包的`obfuscation.txt`文件中,而其他混淆规则不会。
720e41f4b71Sopenharmony_ci
721e41f4b71Sopenharmony_ci```
722e41f4b71Sopenharmony_ci// 混淆选项
723e41f4b71Sopenharmony_ci-enable-property-obfuscation
724e41f4b71Sopenharmony_ci-enable-string-property-obfuscation
725e41f4b71Sopenharmony_ci-enable-toplevel-obfuscation
726e41f4b71Sopenharmony_ci-compact
727e41f4b71Sopenharmony_ci-remove-log
728e41f4b71Sopenharmony_ci
729e41f4b71Sopenharmony_ci// 保留选项
730e41f4b71Sopenharmony_ci-keep-property-name
731e41f4b71Sopenharmony_ci-keep-global-name
732e41f4b71Sopenharmony_ci```
733e41f4b71Sopenharmony_ci
734e41f4b71Sopenharmony_ci**library中混淆注意事项**
735e41f4b71Sopenharmony_ci
736e41f4b71Sopenharmony_ci1. 如果`consumerFiles`指定的混淆配置文件中包含上述混淆选项,当其他模块依赖该HAR包时,这些混淆选项会与主模块的混淆规则合并,从而影响主模块。因此不建议开发者在`consumer-rules.txt`文件中配置混淆选项,建议仅配置保留选项。
737e41f4b71Sopenharmony_ci
738e41f4b71Sopenharmony_ci2. 如果在`consumerFiles`指定的混淆配置文件中添加`-keep-dts`选项,会被转换成`-keep-global-name`和`-keep-property-name`。
739e41f4b71Sopenharmony_ci
740e41f4b71Sopenharmony_ci## 报错栈还原
741e41f4b71Sopenharmony_ci
742e41f4b71Sopenharmony_ci经过混淆的应用程序中代码名称会发生更改,crash时打印的报错栈更难以理解,因为报错栈与源码不完全一致。开发人员可使用DevEco Studio命令工具Command Line Tools中的hstack插件来还原源码堆栈,进而分析问题。反混淆工具需要使用应用编译过程中生成的sourceMaps.map文件以及混淆名称映射文件nameCache.json文件,因此请本地备份它们。
743e41f4b71Sopenharmony_ci
744e41f4b71Sopenharmony_ci![obfuscation-product](figures/obfuscation-product.png)
745e41f4b71Sopenharmony_ci
746e41f4b71Sopenharmony_ci## 说明
747e41f4b71Sopenharmony_ci
748e41f4b71Sopenharmony_ci* 目前不支持在hvigor构建流程中插入自定义混淆插件
749e41f4b71Sopenharmony_ci* 混淆的HAR包被模块依赖,若模块开启混淆,则HAR包会被二次混淆
750e41f4b71Sopenharmony_ci* DevEco Studio右上角Product选项,将其中Build Mode选择release,可开启release编译模式
751e41f4b71Sopenharmony_ci![product-release](figures/product-release.png)
752e41f4b71Sopenharmony_ci
753e41f4b71Sopenharmony_ci## FAQ
754e41f4b71Sopenharmony_ci
755e41f4b71Sopenharmony_ci### 混淆各功能上线SDK版本
756e41f4b71Sopenharmony_ci
757e41f4b71Sopenharmony_ci| 混淆选项 | 功能描述  | 最低版本号 |
758e41f4b71Sopenharmony_ci| ------- | --------- | ------ |
759e41f4b71Sopenharmony_ci| -disable-obfuscation         | 关闭混淆 | 4.0.9.2 |
760e41f4b71Sopenharmony_ci| -enable-property-obfuscation | 属性混淆 | 4.0.9.2 |
761e41f4b71Sopenharmony_ci| -enable-string-property-obfuscation | 字符串字面量属性名混淆 | 4.0.9.2 |
762e41f4b71Sopenharmony_ci| -enable-toplevel-obfuscation | 顶层作用域名称混淆 | 4.0.9.2 |
763e41f4b71Sopenharmony_ci| -enable-filename-obfuscation | HAR包文件/文件夹名称混淆 <br> HAP/HSP文件/文件夹名称混淆 | 4.1.5.3 <br> 5.0.0.19 |
764e41f4b71Sopenharmony_ci| -enable-export-obfuscation   | 向外导入或导出的名称混淆 | 4.1.5.3 |
765e41f4b71Sopenharmony_ci| -compact                     | 去除不必要的空格符和所有的换行符 | 4.0.9.2 |
766e41f4b71Sopenharmony_ci| -remove-log                  | 删除特定场景中的console.* | 4.0.9.2 |
767e41f4b71Sopenharmony_ci| -print-namecache             | 将名称缓存保存到指定的文件路径 | 4.0.9.2 |
768e41f4b71Sopenharmony_ci| -apply-namecache             | 复用指定的名称缓存文件 | 4.0.9.2 |
769e41f4b71Sopenharmony_ci| -remove-comments             | 删除文件中所有注释 | 4.1.5.3 |
770e41f4b71Sopenharmony_ci| -keep-property-name          | 保留属性名 | 4.0.9.2 |
771e41f4b71Sopenharmony_ci| -keep-global-name            | 保留顶层作用域的名称 | 4.0.9.2 |
772e41f4b71Sopenharmony_ci| -keep-file-name              | 保留HAR包的文件/文件夹的名称 <br> 保留HAP/HSP包的文件/文件夹的名称 | 4.1.5.3 <br> 5.0.0.19 |
773e41f4b71Sopenharmony_ci| -keep-dts                    | 保留指定路径的.d.ts文件中的名称 | 4.0.9.2 |
774e41f4b71Sopenharmony_ci| -keep-comments               | 保留编译生成的声明文件中class, function, namespace, enum, struct, interface, module, type及属性上方的JsDoc注释 | 4.1.5.3 |
775e41f4b71Sopenharmony_ci| -keep                        | 保留指定路径中的所有名称 | 5.0.0.18 |
776e41f4b71Sopenharmony_ci| 通配符                       | 名称类和路径类的保留选项支持通配符 | 5.0.0.24 |
777e41f4b71Sopenharmony_ci
778e41f4b71Sopenharmony_ci### 如何查看混淆效果
779e41f4b71Sopenharmony_ci
780e41f4b71Sopenharmony_ci开发人员可以在编译产物build目录中找到混淆后的文件,以及混淆生成的名称映射表及系统API白名单文件。
781e41f4b71Sopenharmony_ci
782e41f4b71Sopenharmony_ci* 混淆后的文件目录:`build/default/[...]/release/模块名`
783e41f4b71Sopenharmony_ci* 混淆名称映射表及系统API白名单目录:`build/default/[...]/release/obfuscation`
784e41f4b71Sopenharmony_ci  * 名称映射表文件:nameCache.json,该文件记录了源码名称混淆的映射关系。
785e41f4b71Sopenharmony_ci  * 系统API白名单文件:systemApiCache.json,该文件记录了SDK中的接口与属性名称,与其重名的源码不会被混淆。
786e41f4b71Sopenharmony_ci
787e41f4b71Sopenharmony_ci  ![build-product](figures/build-product.png)
788e41f4b71Sopenharmony_ci
789e41f4b71Sopenharmony_ci### 如何排查功能异常
790e41f4b71Sopenharmony_ci
791e41f4b71Sopenharmony_ci1. 先在obfuscation-rules.txt配置-disable-obfuscation选项关闭混淆,确认问题是否由混淆引起。
792e41f4b71Sopenharmony_ci2. 若确认是开启混淆后功能出现异常,请先阅读文档了解[-enable-property-obfuscation](#混淆选项)、[-enable-toplevel-obfuscation](#混淆选项)、[-enable-filename-obfuscation](#混淆选项)、[-enable-export-obfuscation](#混淆选项)等混淆规则的能力以及哪些语法场景需要配置白名单来保证应用功能正常。下文简要介绍默认开启的四项选项功能,细节还请阅读对应选项的完整描述。
793e41f4b71Sopenharmony_ci    1.[-enable-toplevel-obfuscation](#混淆选项)为顶层作用域名称混淆开关。
794e41f4b71Sopenharmony_ci    2.[-enable-property-obfuscation](#混淆选项)为属性混淆开关,配置白名单的主要场景为网络数据访问、json字段访问、动态属性访问、调用so库接口等不能混淆场景,需要使用[-keep-property-name](#保留选项)来保留指定的属性名称。
795e41f4b71Sopenharmony_ci    3.[-enable-export-obfuscation](#混淆选项)为导出名称混淆,一般与1、2选项配合使用;配置白名单的主要场景为模块对外接口不能混淆,需要使用[-keep-global-name](#保留选项)来指定保留导出/导入名称。
796e41f4b71Sopenharmony_ci    4.[-enable-filename-obfuscation](#混淆选项)为文件名混淆,配置白名单的主要场景为动态import或运行时直接加载的文件路径,需要使用[-keep-file-name](#保留选项)来保留这些文件路径及名称。
797e41f4b71Sopenharmony_ci3. 参考FAQ中的[常见报错案例](#常见报错案例),若是相似场景可参考对应的解决方法快速解决。
798e41f4b71Sopenharmony_ci4. 若常见案例中未找到相似案例,建议依据各项配置功能正向定位(若不需要相应功能,可删除对应配置项)。
799e41f4b71Sopenharmony_ci5. 应用运行时崩溃分析方法:
800e41f4b71Sopenharmony_ci    1.打开应用运行日志或者点击DevEco Studio中出现的Crash弹窗,找到运行时崩溃栈。
801e41f4b71Sopenharmony_ci    2.应用运行时崩溃栈中的行号为[编译产物](#如何查看混淆效果)的行号,方法名也可能为混淆后名称;因此排查时建议直接根据崩溃栈查看编译产物,进而分析哪些名称不能被混淆,然后将其配置进白名单中。
802e41f4b71Sopenharmony_ci6. 应用在运行时未崩溃但出现功能异常的分析方法(比如白屏):
803e41f4b71Sopenharmony_ci    1.打开应用运行日志:选择HiLog,检索与功能异常直接相关的日志,定位问题发生的上下文。
804e41f4b71Sopenharmony_ci    2.定位异常代码段:通过分析日志,找到导致功能异常的具体代码块。
805e41f4b71Sopenharmony_ci    3.增强日志输出:在疑似异常的功能代码中,对处理的数据字段增加日志记录。
806e41f4b71Sopenharmony_ci    4.分析并确定关键字段:通过对新增日志输出的分析,识别是否由于混淆导致该字段的数据异常。
807e41f4b71Sopenharmony_ci    5.配置白名单保护关键字段:将确认在混淆后对应用功能产生直接影响的关键字段添加到白名单中。
808e41f4b71Sopenharmony_ci
809e41f4b71Sopenharmony_ci### 常见报错案例
810e41f4b71Sopenharmony_ci
811e41f4b71Sopenharmony_ci#### 开启-enable-property-obfuscation选项可能出现的问题
812e41f4b71Sopenharmony_ci
813e41f4b71Sopenharmony_ci**案例一:报错内容为 Cannot read property 'xxx' of undefined**
814e41f4b71Sopenharmony_ci
815e41f4b71Sopenharmony_ci```
816e41f4b71Sopenharmony_ci// 混淆前
817e41f4b71Sopenharmony_ciconst jsonData = ('./1.json')
818e41f4b71Sopenharmony_cilet jsonStr = JSON.parse(jsonData)
819e41f4b71Sopenharmony_cilet jsonObj = jsonStr.jsonProperty
820e41f4b71Sopenharmony_ci
821e41f4b71Sopenharmony_ci// 混淆后
822e41f4b71Sopenharmony_ciconst jsonData = ('./1.json')
823e41f4b71Sopenharmony_cilet jsonStr = JSON.parse(jsonData)
824e41f4b71Sopenharmony_cilet jsonObj = jsonStr.i
825e41f4b71Sopenharmony_ci```
826e41f4b71Sopenharmony_ci
827e41f4b71Sopenharmony_ci开启属性混淆后,"jsonProperty" 被混淆成随机字符 "i",但json文件中为原始名称,从而导致值为undefined。
828e41f4b71Sopenharmony_ci
829e41f4b71Sopenharmony_ci**解决方案:** 使用`-keep-property-name`选项将json文件里的字段配置到白名单。
830e41f4b71Sopenharmony_ci
831e41f4b71Sopenharmony_ci**案例二:使用了数据库相关的字段,开启属性混淆后,出现报错**
832e41f4b71Sopenharmony_ci
833e41f4b71Sopenharmony_ci报错内容为 `table Account has no column named a23 in 'INSET INTO Account(a23)'`
834e41f4b71Sopenharmony_ci
835e41f4b71Sopenharmony_ci代码里使用了数据库字段,混淆时该SQL语句中字段名称被混淆,但数据库中字段为原始名称,从而导致报错。
836e41f4b71Sopenharmony_ci
837e41f4b71Sopenharmony_ci**解决方案:** 使用`-keep-property-name`选项将使用到的数据库字段配置到白名单。
838e41f4b71Sopenharmony_ci
839e41f4b71Sopenharmony_ci#### 开启-enable-export-obfuscation和-enable-toplevel-obfuscation选项可能出现的问题
840e41f4b71Sopenharmony_ci
841e41f4b71Sopenharmony_ci**当开启这两个选项时,主模块调用其他模块方法时涉及的方法名称混淆情况如下:**
842e41f4b71Sopenharmony_ci
843e41f4b71Sopenharmony_ci| 主模块 | 依赖模块 | 导入与导出的名称混淆情况 |
844e41f4b71Sopenharmony_ci| ------- | ------- | ----------------------------|
845e41f4b71Sopenharmony_ci| HAP/HSP | HSP     | HSP和主模块是独立编译的,混淆后名称会不一致,因此都需要配置白名单 |
846e41f4b71Sopenharmony_ci| HAP/HSP | 本地HAR | 本地HAR与主模块一起编译,混淆后名称一致 |
847e41f4b71Sopenharmony_ci| HAP/HSP | 三方库  | 三方库中导出的名称及其属性会被收集到白名单,因此导入和导出时都不会被混淆 |
848e41f4b71Sopenharmony_ci
849e41f4b71Sopenharmony_ciHSP需要将给其他模块用的方法配置到白名单中。因为主模块里也需要配置相同的白名单,所以推荐将HSP配置了白名单的混淆文件(假设名称为hsp-white-list.txt)添加到依赖它的模块的混淆配置项里,即下图files字段里。
850e41f4b71Sopenharmony_ci
851e41f4b71Sopenharmony_ci![obfuscation-config](figures/obfuscation-config.png)
852e41f4b71Sopenharmony_ci
853e41f4b71Sopenharmony_ci**案例一:动态导入某个类,类定义的地方被混淆,导入类名时却没有混淆,导致报错**
854e41f4b71Sopenharmony_ci
855e41f4b71Sopenharmony_ci```
856e41f4b71Sopenharmony_ci// 混淆前
857e41f4b71Sopenharmony_ciexport class Test1 {}
858e41f4b71Sopenharmony_ci
859e41f4b71Sopenharmony_cilet mytest = (await import('./file')).Test1
860e41f4b71Sopenharmony_ci
861e41f4b71Sopenharmony_ci// 混淆后
862e41f4b71Sopenharmony_ciexport class w1 {}
863e41f4b71Sopenharmony_ci
864e41f4b71Sopenharmony_cilet mytest = (await import('./file')).Test1
865e41f4b71Sopenharmony_ci```
866e41f4b71Sopenharmony_ci
867e41f4b71Sopenharmony_ci导出的类 "Test1" 是一个顶层作用域名,当 "Test1" 被动态使用时,它是一个属性。因为没有开启`-enable-property-obfuscation`选项,所以名称混淆了,但属性没有混淆。
868e41f4b71Sopenharmony_ci
869e41f4b71Sopenharmony_ci**解决方案:** 使用`-keep-global-name`选项将 "Test1" 配置到白名单。
870e41f4b71Sopenharmony_ci
871e41f4b71Sopenharmony_ci**案例二:在使用namespace中的方法时,该方法定义的地方被混淆了,但使用的地方却没有被混淆,导致报错**
872e41f4b71Sopenharmony_ci
873e41f4b71Sopenharmony_ci```
874e41f4b71Sopenharmony_ci// 混淆前
875e41f4b71Sopenharmony_ciexport namespace ns1 {
876e41f4b71Sopenharmony_ci  export class person1 {}
877e41f4b71Sopenharmony_ci}
878e41f4b71Sopenharmony_ci
879e41f4b71Sopenharmony_ciimport {ns1} from './file1'
880e41f4b71Sopenharmony_cilet person1 = new ns1.person1()
881e41f4b71Sopenharmony_ci
882e41f4b71Sopenharmony_ci// 混淆后
883e41f4b71Sopenharmony_ciexport namespace a3 {
884e41f4b71Sopenharmony_ci  export class b2 {}
885e41f4b71Sopenharmony_ci}
886e41f4b71Sopenharmony_ci
887e41f4b71Sopenharmony_ciimport {a3} from './file1'
888e41f4b71Sopenharmony_cilet person1 = new a3.person1()
889e41f4b71Sopenharmony_ci```
890e41f4b71Sopenharmony_ci
891e41f4b71Sopenharmony_cinamespace里的 "person1" 属于顶层作用域的class名称,通过 "ns1.person1" 来调用时,它是属于一个属性,由于未开启属性混淆,所以在使用它时没有被混淆。
892e41f4b71Sopenharmony_ci
893e41f4b71Sopenharmony_ci**解决方案:**
894e41f4b71Sopenharmony_ci
895e41f4b71Sopenharmony_ci1. 开启`-enable-property-obfuscation`选项。
896e41f4b71Sopenharmony_ci2. 将namespace里导出的方法使用`-keep-global-name`选项添加到白名单。
897e41f4b71Sopenharmony_ci
898e41f4b71Sopenharmony_ci**案例三:使用了`declare global`,混淆后报语法错误**
899e41f4b71Sopenharmony_ci
900e41f4b71Sopenharmony_ci```
901e41f4b71Sopenharmony_ci// 混淆前
902e41f4b71Sopenharmony_cideclare global {
903e41f4b71Sopenharmony_ci  var age : string
904e41f4b71Sopenharmony_ci}
905e41f4b71Sopenharmony_ci
906e41f4b71Sopenharmony_ci// 混淆后
907e41f4b71Sopenharmony_cideclare a2 {
908e41f4b71Sopenharmony_ci  var b2 : string
909e41f4b71Sopenharmony_ci}
910e41f4b71Sopenharmony_ci```
911e41f4b71Sopenharmony_ci
912e41f4b71Sopenharmony_ci报错内容为 `SyntaxError: Unexpected token`
913e41f4b71Sopenharmony_ci
914e41f4b71Sopenharmony_ci**解决方案:** 使用`-keep-global-name`选项将`__global`配置到白名单中。
915e41f4b71Sopenharmony_ci
916e41f4b71Sopenharmony_ci#### 未开启-enable-string-property-obfuscation混淆选项,字符串字面量属性名却被混淆,导致字符串字面量属性名的值为undefined
917e41f4b71Sopenharmony_ci
918e41f4b71Sopenharmony_ci```
919e41f4b71Sopenharmony_ciperson["age"] = 22; // 混淆前
920e41f4b71Sopenharmony_ci
921e41f4b71Sopenharmony_ciperson["b"] = 22; // 混淆后
922e41f4b71Sopenharmony_ci```
923e41f4b71Sopenharmony_ci
924e41f4b71Sopenharmony_ci**解决方案:**
925e41f4b71Sopenharmony_ci
926e41f4b71Sopenharmony_ci1. 确认是否有依赖的HAR包开启了字符串属性名混淆,若开启了,则会影响主工程,需将其关闭。
927e41f4b71Sopenharmony_ci2. 若不能关闭`-enable-string-property-obfuscation`选项,将属性名配置到白名单中。
928e41f4b71Sopenharmony_ci3. 若依赖HAR包未开启字符串属性名混淆,同时SDK版本小于4.1.5.3,请更新SDK。
929e41f4b71Sopenharmony_ci
930e41f4b71Sopenharmony_ci#### 开启-enable-filename-obfuscation选项后,可能会出现的问题
931e41f4b71Sopenharmony_ci
932e41f4b71Sopenharmony_ci**案例一:报错为 Error Failed to get a resolved OhmUrl for 'D:code/MyApplication/f12/library1/pages/d.ets' imported by 'undefined'**
933e41f4b71Sopenharmony_ci
934e41f4b71Sopenharmony_ci工程的目录结构如下图所示,模块library1的外层还有目录 "directory",开启文件名混淆后,"directory" 被混淆为f12,导致路径找不到。
935e41f4b71Sopenharmony_ci
936e41f4b71Sopenharmony_ci![directory-offuscation](figures/directory-obfuscation.png)
937e41f4b71Sopenharmony_ci
938e41f4b71Sopenharmony_ci**解决方案:**
939e41f4b71Sopenharmony_ci
940e41f4b71Sopenharmony_ci1. 如果工程的目录结构和报错内容都相似,请将SDK更新至最低5.0.0.26版本。
941e41f4b71Sopenharmony_ci2. 使用`-keep-file-name`将模块外层的目录名 "directory" 配置到白名单中。
942e41f4b71Sopenharmony_ci
943e41f4b71Sopenharmony_ci**案例二:报错为 Cannot find module 'ets/appability/AppAbility' which is application Entry Point**
944e41f4b71Sopenharmony_ci
945e41f4b71Sopenharmony_ci由于系统会在应用运行时加载ability文件,用户需要手动配置相应的白名单,防止指定文件被混淆,导致运行失败。
946e41f4b71Sopenharmony_ci
947e41f4b71Sopenharmony_ci**解决方案:** 使用`-keep-file-name`选项,将`src/main/module.json5`文件中,'srcEntry'字段所对应的路径配置到白名单中。
948e41f4b71Sopenharmony_ci
949e41f4b71Sopenharmony_ci```
950e41f4b71Sopenharmony_ci-keep-file-name
951e41f4b71Sopenharmony_ciappability
952e41f4b71Sopenharmony_ciAppAbility
953e41f4b71Sopenharmony_ci```
954e41f4b71Sopenharmony_ci
955e41f4b71Sopenharmony_ci#### 使用-keep-global-name选项配置白名单时,可能会出现的问题
956e41f4b71Sopenharmony_ci
957e41f4b71Sopenharmony_ci报错内容为 `Cannot read properties of undefined (reading 'has')`
958e41f4b71Sopenharmony_ci
959e41f4b71Sopenharmony_ci**解决方案:** 将SDK更新至最低4.1.6.3版本。
960