Android开发中混淆后Gson序列化、反序列化的那些坑,网站开发前后端分离

news/2024/5/20 15:30:36/文章来源:https://blog.csdn.net/m0_64604893/article/details/122023321

为什么呢?

  • 因为反序列化创建对象本质还是利用反射, 会根据 json 字符串的 key 作为属性名称, value 则对应属性值.

如何解决

  • 将序列化和反序列化的类排除混淆

  • 使用 @SerializedName 注解字段

@SerializedName(parameter) 通过注解属性实现了

  • 序列化的结果中, 指定该属性 key 为 parameter 的值.

  • 反序列化生成的对象中, 用来匹配 key 与 parameter 并赋予属性值.

一个简单的用法为

public class Item {

@SerializedName(“name”)

public String name;

@SerializedName(“id”)

public int id;

}

当然也可以直接这么写

public class Item implements Serializable{

public String name;

public int id;

}

上面是通过添加 @SerializedName 注解实现混淆之后反序列化出现的问题,下面我们说下将将序列化和反序列化的类排除混淆该怎么做。

package com.baidu.bean;

public class Item {

public String name;

public int id;

public static class PageConfig {

public String type;

}

}

Item 中增加了一个内部类 PageConfig。

这里敲黑板了

1.Item 里面的字段、Item 里面引用到的类和 Item 里面的内部类 PageConfig 都需要实现序列化 (implements Serializable);

  1. 如果不是 implements Serializable 实现序列化,而是给每个字段加上 @SerializedName 注解,那么务必注意:Item 里面的字段、Item 里面引用到的类的和 Item 里面的内部类的字段都需要加上 @SerializedName 注解,否则会出现莫名其妙的问题:不会崩溃,就是各种奇怪现象,而在 debug 下又不出现这个问题。

最常见的做法是:

-keep class com.baidu.bean.** { *; }

含义是:将 bean 目录下包括子目录下的类排除不被混淆

单独排除某个类可以这么写:

-keep class com.baidu.bean {*;}

单独排除某个类的内部类需要这么写:

-keep class class com.baidu.bean.Item$PageConfig {*;}

如果很多实体类里面有内部类,建议组合起来写:

-keep class com.baidu.bean.**{ *;}

-keep class com.baidu.bean.**$*{ *;}

另外,下面的写法也是可以的,主要以上面的写法为主。具体要使用哪种,读者可以自己根据需要使用。

-keep class com.baidu.bean.$** {;}

-keep class com.baidu.bean.$ {*;}

-keep class com.baidu.bean.**$* {*;}

上面出现了 * 和 ** 通配符的配置,为了便于加深印象,这里延伸阅读下:

Android 混淆最佳实践

============================================================================

1. 混淆配置

android{

buildTypes {

release {

buildConfigField “boolean”, “LOG_DEBUG”, “false” //不显示log

minifyEnabled true

shrinkResources true

proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’

signingConfig signingConfigs.config

}

}

}

因为开启混淆会使编译时间变长,所以 debug 模式下不开启。我们需要做的是:

  1. release下minifyEnabled的值改为true,打开混淆;

  2. 加上shrinkResources true,打开资源压缩。

3.buildConfigField 不显示 log 日志

4.signingConfig signingConfigs.config配置签名文件文件

自定义混淆规则

=====================================================================

自定义混淆方案适用于大部分的项目

#指定压缩级别

-optimizationpasses 5

#不跳过非公共的库的类成员

-dontskipnonpubliclibraryclassmembers

#混淆时采用的算法

-optimizations !code/simplification/arithmetic,!field/,!class/merging/

#把混淆类中的方法名也混淆了

-useuniqueclassmembernames

#优化时允许访问并修改有修饰符的类和类的成员

-allowaccessmodification

#将文件来源重命名为“SourceFile”字符串

-renamesourcefileattribute SourceFile

#保留行号

-keepattributes SourceFile,LineNumberTable

#保持泛型

-keepattributes Signature

#保持所有实现 Serializable 接口的类成员

-keepclassmembers class * implements java.io.Serializable {

static final long serialVersionUID;

private static final java.io.ObjectStreamField[] serialPersistentFields;

private void writeObject(java.io.ObjectOutputStream);

private void readObject(java.io.ObjectInputStream);

java.lang.Object writeReplace();

java.lang.Object readResolve();

}

#Fragment不需要在AndroidManifest.xml中注册,需要额外保护下

-keep public class * extends android.support.v4.app.Fragment

-keep public class * extends android.app.Fragment

保持测试相关的代码

-dontnote junit.framework.**

-dontnote junit.runner.**

-dontwarn android.test.**

-dontwarn android.support.test.**

-dontwarn org.junit.**

真正通用的、需要添加的就是上面这些,除此之外,需要每个项目根据自身的需求添加一些混淆规则:

第三方库所需的混淆规则。正规的第三方库一般都会在接入文档中写好所需混淆规则,使用时注意添加。

在运行时动态改变的代码,例如反射。比较典型的例子就是会与 json 相互转换的实体类。假如项目命名规范要求实体类都要放在 model 包下的话,可以添加类似这样的代码把所有实体类都保持住:-keep public class **.*Model*.** {*;}

JNI 中调用的类。

WebView 中JavaScript调用的方法

Layout 布局使用的 View 构造函数、android:onClick等。

检查混淆结果

====================================================================

混淆过的包必须进行检查,避免因混淆引入的 bug。

一方面,需要从代码层面检查。使用上文的配置进行混淆打包后在<module-name>/build/outputs/mapping/release/目录下会输出以下文件:

dump.txt

描述 APK 文件中所有类的内部结构

mapping.txt

提供混淆前后类、方法、类成员等的对照表

seeds.txt

列出没有被混淆的类和成员

usage.txt

列出被移除的代码

我们可以根据 seeds.txt 文件检查未被混淆的类和成员中是否已包含所有期望保留的,再根据 usage.txt文件查看是否有被误移除的代码。

另一方面,需要从测试方面检查。将混淆过的包进行全方面测试,检查是否有 bug 产生。

解出混淆栈

===================================================================

混淆后的类、方法名等等难以阅读,这固然会增加逆向工程的难度,但对追踪线上 crash 也造成了阻碍。我们拿到 crash 的堆栈信息后会发现很难定位,这时需要将混淆反解。

<sdk-root>/tools/proguard/路径下有附带的的反解工具(Window 系统为proguardgui.bat,Mac 或 Linux 系统为proguardgui.sh)。

这里以 Window 平台为例。双击运行 proguardgui.bat 后,可以看到左侧的一行菜单。点击 ReTrace,选择该混淆包对应的 mapping 文件(混淆后在 /build/outputs/mapping/release/ 路径下会生成 mapping.txt 文件,它的作用是提供混淆前后类、方法、类成员等的对照表),再将 crash 的 stack trace 黏贴进输入框中,点击右下角的 ReTrace ,混淆后的堆栈信息就显示出来了。

以上使用 GUI 程序进行操作,另一种方式是利用该路径下的 retrace 工具通过命令行进行反解,命令是

retrace.bat|retrace.sh [-verbose] mapping.txt [<stacktrace_file>]

例如:

retrace.bat -verbose mapping.txt obfuscated_trace.txt

注意事项:

所有在 AndroidManifest.xml 涉及到的类已经自动被保持,因此不用特意去添加这块混淆规则。(很多老的混淆文件里会加,现在已经没必要)

proguard-android.txt已经存在一些默认混淆规则,没必要在 proguard-rules.pro 重复添加

混淆简介

==================================================================

Android 中的 “混淆” 可以分为两部分,一部分是Java 代码的优化与混淆,依靠 proguard混淆器来实现;另一部分是资源压缩,将移除项目及依赖的库中未被使用的资源 (资源压缩严格意义上跟混淆没啥关系,但一般我们都会放一起用)。

代码压缩


代码压缩流程

代码混淆是包含了代码压缩、优化、混淆等一系列行为的过程。如上图所示,混淆过程会有如下几个功能:

压缩。移除无效的类、类成员、方法、属性等;

优化。分析和优化方法的二进制代码;根据proguard-android-optimize.txt中的描述,优化可能会造成一些潜在风险,不能保证在所有版本的 Dalvik 上都正常运行。

混淆。把类名、属性名、方法名替换为简短且无意义的名称;

预校验。添加预校验信息。这个预校验是作用在 Java 平台上的,Android 平台上不需要这项功能,去掉之后还可以加快混淆速度。

这四个流程默认开启。

Android项目中我们可以选择将 “优化” 和“预校验”关闭,对应命令是-dontoptimize、-dontpreverify(当然,默认的 proguard-android.txt文件已包含这两条混淆命令,不需要开发者额外配置)。

资源压缩

==================================================================

资源压缩将移除项目及依赖的库中未被使用的资源,这在减少apk 包体积上会有不错的效果,一般建议开启。具体做法是在 build.grade文件中,将shrinkResources属性设置为true。需要注意的是,只有在用minifyEnabled true开启了代码压缩后,资源压缩才会生效。

资源压缩包含了 “合并资源” 和“移除资源”两个流程。

“合并资源” 流程中,名称相同的资源被视为重复资源会被合并。需要注意的是,这一流程不受shrinkResources属性控制,也无法被禁止,gradle必然会做这项工作,因为假如不同项目中存在相同名称的资源将导致错误。gradle 在四处地方寻找重复资源:

src/main/res/ 路径

不同的构建类型(debugrelease等等)

不同的构建渠道

项目依赖的第三方库

合并资源时按照如下优先级顺序

依赖 -> main -> 渠道 -> 构建类型

假如重复资源同时存在于 main 文件夹和不同渠道中,gradle 会选择保留渠道中的资源。

同时,如果重复资源在同一层次出现,比如src/main/res/ 和 src/main/res2/,则 gradle无法完成资源合并,这时会报资源合并错误。

“移除资源” 流程则见名知意,需要注意的是,类似代码,混淆资源移除也可以定义哪些资源需要被保留,这点在下文给出。

自定义混淆规则

=====================================================================

在上文 “混淆配置” 中有这样一行代码

proguardFiles getDefaultProguardFile(‘proguard-android.txt’), ‘proguard-rules.pro’

这行代码定义了混淆规则由两部分构成:位于 SDK 的 tools/proguard/ 文件夹中的 proguard-android.txt 的内容以及默认放置于模块根目录的 proguard-rules.pro 的内容。前者是 SDK 提供的默认混淆文件,后者是开发者自定义混淆规则的地方。

常见的混淆指令

=====================================================================

  • optimizationpasses

  • dontoptimize

  • dontusemixedcaseclassnames

  • dontskipnonpubliclibraryclasses

  • dontpreverify

  • dontwarn

  • verbose

  • optimizations

  • keep

  • keepnames

  • keepclassmembers

  • keepclassmembernames

  • keepclasseswithmembers

  • keepclasseswithmembernames

更多详细的请到官网

需要特别介绍的是与保持相关元素不参与混淆的规则相关的几种命令:

| 命令 | 作用 |

| — | — |

| -keep | 防止类和成员被移除或者被重命名 |

| -keepnames | 防止类和成员被重命名 |

| -keepclassmembers | 防止成员被移除或者被重命名 |

| -keepnames | 防止成员被重命名 |

| -keepclasseswithmembers | 防止拥有该成员的类和成员被移除或者被重命名 |

| -keepclasseswithmembernames | 防止拥有该成员的类和成员被重命名 |

保持元素不参与混淆的规则


[保持命令] [类] {

[成员]

}

“类” 代表类相关的限定条件,它将最终定位到某些符合该限定条件的类。它的内容可以使用:

  • 具体的类

  • 访问修饰符(public、protected、private)

  • 通配符 *,匹配任意长度字符,但不含包名分隔符 (.)

  • 通配符 **,匹配任意长度字符,并且包含包名分隔符 (.)

  • extends,即可以指定类的基类

  • implement,匹配实现了某接口的类

  • $,内部类

“成员” 代表类成员相关的限定条件,它将最终定位到某些符合该限定条件的类成员。它的内容可以使用:

  • 匹配所有构造器

  • 匹配所有域

  • 匹配所有方法

  • 通配符 *,匹配任意长度字符,但不含包名分隔符 (.)

  • 通配符 **,匹配任意长度字符,并且包含包名分隔符 (.)

  • 通配符 ***,匹配任意参数类型

  • …,匹配任意长度的任意类型参数。比如 void test(…) 就能匹配任意 void test(String a) 或者是 void test(int a, String b) 这些方法。

  • 访问修饰符(public、protected、private)

举个例子,假如需要将 com.biaobiao.test 包下所有继承 Activity 的 public 类及其构造函数都保持住,可以这样写:

-keep public class com.biaobiao.test.** extends Android.app.Activity {

}

常用自定义混淆规则


  • 不混淆某个类

-keep public class com.biaobiao.example.Test { *; }

不混淆某个包所有的类

-keep class com.biaobiao.test.** { *; }

}

不混淆某个类的子类

-keep public class * extends com.biaobiao.example.Test { *; }

不混淆所有类名中包含了 “model” 的类及其成员

-keep public class * extends com.biaobiao.example.Test { *; }

不混淆某个接口的实现

-keep class * implements com.biaobiao.example.TestInterface { *; }

不混淆某个类的构造方法

-keepclassmembers class com.biaobiao.example.Test {

public ();

}

不混淆某个类的特定的方法

-keepclassmembers class com.biaobiao.example.Test {

public void test(java.lang.String);

}

}

不混淆某个类的内部类

-keep class com.biaobiao.example.Test$* {

*;

}

自定义资源保持规则


1. keep.xml

shrinkResources true开启资源压缩后,所有未被使用的资源默认被移除。假如你需要定义哪些资源必须被保留,在 res/raw/ 路径下创建一个 xml 文件,例如keep.xml

通过一些属性的设置可以实现定义资源保持的需求,可配置的属性有:

  • keep 定义哪些资源需要被保留(资源之间用 “,” 隔开)

  • discard 定义哪些资源需要被移除(资源之间用 “,” 隔开)

  • shrinkMode 开启严格模式

  • 当代码中通过Resources.getIdentifier() 用动态的字符串来获取并使用资源时,普通的资源引用检查就可能会有问题。例如,如下代码会导致所有以 “img_” 开头的资源都被标记为已使用。

当代码中通过 Resources.getIdentifier() 用动态的字符串来获取并使用资源时,普通的资源引用检查就可能会有问题。例如,如下代码会导致所有以 “img_” 开头的资源都被标记为已使用。

String name = String.format(“img_%1d”, angle + 1);

res = getResources().getIdentifier(name, “drawable”, getPackageName());

我们可以设置 tools:shrinkModestrict来开启严格模式,使只有确实被使用的资源被保留。

以上就是自定义资源保持规则相关的配置,举个例子:

<?xml version="1.0" encoding="utf-8"?>

<resources xmlns:tools=“http://schemas.android.com/tools”

tools:keep="@layout/l_used*_c,@layout/l_used_a,@layout/l_used_b*"

tools:discard="@layout/unused2"

tools:shrinkMode=“strict”/>

移除替代资源


一些替代资源,例如多语言支持的 strings.xml,多分辨率支持的 layout.xml 等,在我们不需要使用又不想删除掉时,可以使用资源压缩将它们移除。

我们使用 resConfig 属性来指定需要支持的属性,例如

一些替代资源,例如多语言支持的strings.xml,多分辨率支持的 layout.xml等,在我们不需要使用又不想删除掉时,可以使用资源压缩将它们移除。

我们使用 resConfig属性来指定需要支持的属性,例如

android {

defaultConfig {

resConfigs “en”, “fr”

}

}

其他未显式声明的语言资源将被移除。

最后附上一个我在实际项目中的混淆方案

================================================================================

proguard-android.txt文件内容

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_850820.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Hexo+Coding搭建自己的博客网站系列1-本地环境部署

前言 我的博客&#xff1a;https://fitz1318.top/ 最近我终于实现了自己很久之前关于搭建自己专属的博客网站的目标&#xff0c;现在把搭建期间的过程和走过的坑记录下来&#xff0c;如果你对搭建自己的网站有兴趣&#xff0c;不妨可以参考一下我的文章。 首先我说下自己的版本…

Hexo+Coding搭建自己的博客网站系列2-部署博客到Coding上

前言 欢迎浏览我的网站https://fitz1318.top/ 最初&#xff0c;我是选择部署到Github上的&#xff0c;但是最后在弄百度收录时出现了问题&#xff0c;Github Pages屏蔽了百度爬虫&#xff0c;这样子你的博客就没办法被百度收录了。 注册并新建仓库 Coding的网址 &#xff0c…

Hexo+Coding搭建自己的博客网站系列3-详述站点全局配置文件

Hexo 目录如下图 欢迎浏览我的博客&#xff1a;https://fitz1318.top/ 这是Blog文件的目录。从上到下依次解释 node_modules:hexo整个项目的环境依赖&#xff0c;hexo初始化时自动生成的。public:存放的是整个项目的页面&#xff0c;样式&#xff0c;及逻辑代码。scaffolds:s…

【教程】Hexo+Coding搭建自己的博客网站系列5-Next6.7版本主题深度美化

在我进行主题优化的时候&#xff0c;参考了网上很多文章&#xff0c;但是随着Next版本的变迁&#xff0c;越来越多个性化设置已经被集成到Next中。所以我写了这篇关于Next6.7版本主题优化的方案。有时间和精力的话&#xff0c;这篇文章也会随着Next版本变迁持续更新.欢迎浏览我…

前端开发值得收藏的网站

工作空闲时间&#xff0c;作为前端开发人员&#xff0c;还是希望利用好这段宝贵的时间多学习一些前端资源&#xff0c;了解当前前端知识体系&#xff0c;从整体上对当前行业有一个由浅入深的了解和掌握。后续还会慢慢更新好用的前端相关网站&#xff0c;加油&#xff01; 1.Co…

服务器电脑无限重启,win10电脑蓝屏无限重启_网站服务器运行维护

win10电脑锁屏时间设置_网站服务器运行维护win10电脑锁屏时间设置方法是&#xff1a;1、首先点击【windows】&#xff0c;点击【设置】&#xff1b;2、然后点击【系统】选项&#xff0c;选择【电源和睡眠】选项&#xff1b;3、最后设置锁屏时间即可。第一步&#xff1a;进入Win…

设计响应式网站-Bootstrap(1)

1.Bootstra介绍 2011年&#xff0c;twitter的“一小撮”工程师为了提高他们内部的分析和管理能力&#xff0c;用业余时间为他们的产品构建了一套易用、优雅、灵活、可扩展的前端工具集--BootStrap。Bootstrap由MARK OTTO和Jacob Thornton所设计和建立&#xff0c;在github上开…

财经资讯网站--某联社参数破解

本文仅供学习&#xff0c;如有侵权或问题联系博主&#xff0c;感谢阅读 目标链接&#xff1a;aHR0cHM6Ly93d3cuY2xzLmNuL2RlcHRoP2lkPTEwMDA 抓包分析&#xff1a; 可以看到加密参数只有一个sign&#xff0c;像这种sign的一搜肯定一堆。所以我拿sv去搜了&#xff0c;看着像m…

源码或学习网站

网站 项目管理网站 开源中国&#xff1a;码云 CSDN: Coding GitHub 阅读 教程 |Android Studio 发布开源项目到JCenter 源码 1&#xff1a;APKBUS:使用MVP模式简单地展示知乎日报主页及内容, Github:AZhiHu 2 高仿知乎日报 3 ZhihuDailyPurify - 知乎日报净化 4 菜…

网站开发预备知识

1.网络系统开发模式 &#xff08;1&#xff09;B/S&#xff1a;brower/server 浏览器/服务器 &#xff08;2&#xff09;C/S: client/server 客户端/服务器 2.URL &#xff08;1&#xff09;全称&#xff1a;Uniform Resource Locator 统一资源定位符&#xff08;网址&#xf…

网站收集

一、生活类 1. 蛙蛙工具——找工具 这是一个便捷的在线工具集合网站&#xff0c;集合了数百种实用工具。它的工具查询是非常便捷的&#xff0c;在便民查询中&#xff0c;我们可以查询电话号码的归属地&#xff0c;身份证的所在地&#xff0c;邮政编码的查询等等&#xff0c;蛙…

去除手机浏览器访问CSDN网站的提示

文章目录前言一、烦人的提示二、寻找解决方法三、编写脚本1.去除打开APP提示2.自动展开3.复制代码四、完整代码五、效果展示总结前言 有时候想用手机查查程序问题&#xff0c;用手机浏览器访问总是弹出打开App、登录烦人的提示 一、烦人的提示 用手机看几篇文章&#xff0c;打…

XUESQL-自学SQL网站上的练习题

SQL学习及习题答案( XUESQL) 1.SELECT 查询 请列出所有电影的ID&#xff0c;名称和出版国 SELECT title,id,美国 as country FROM moviesSQL Lesson 7: 外连接&#xff08;OUTER JOINs&#xff09; INNER JOIN 只会保留两个表都存在的数据&#xff08;还记得之前的交集吗&a…

SSH + Lucene + 分页 + 排序 + 高亮 模拟简单新闻网站搜索引擎

前两天看到了一个中国新闻网&#xff0c;这个网站的搜索form的action是 http://search.chinanews.com/search.do 便知道是struts1的产物&#xff0c;现在都用struts2了&#xff0c;所以给自己的任务是实现Struts2 SSH分页浏览新闻、Lucene分页高亮排序搜索新闻这个两个功能。…

个人搭建网站的服务器选择

关于这方面之前一直准备分享一下心得&#xff0c;由于一直比较忙&#xff0c;各种想写的就各种耽搁了&#xff0c;今天给大家总结一下个人或小型企业站该如何选择网站服务器 首先&#xff0c;先弄清楚自己的需求和用途&#xff1a; 1、是建立一个静态页面还是动态页面&#xff…

Hexo+GitHub搭建个人网站全网最详细教程

前言 这个故事很长&#xff0c;还要从一只蝙蝠说起&#xff01; 大二寒假在家闲来无事一直想做一个网站但是苦于没有门路&#xff0c;于是我去各大论坛搜索关于搭建网站的资料&#xff0c;这一搜还真给搜到了&#xff0c;于是这一套HexoGitHub搭建个人博客网站的方略就加入了…

教你快速搭建个人网站

一、搭建环境&#xff1a; 云主机华为云操作系统centos 7.x源码GitHub - wyt1215819315/autoplan: 这是一个自动化的托管系统&#xff0c;目前支持网易云&#xff0c;bilibili&#xff0c;米游社原神签到&#xff0c;测试地址https://auto.oldwu.top协助软件宝塔面板 二、网站…

(入门级)安利学习网站

作为初学者&#xff0c;如何快速入门学习并保持学习的兴趣&#xff0c;好的学习工具必不可少。无论你是跟着老师学习还是自学&#xff0c;菜鸟教程都是比较好的。当然你也可以在网上百度&#xff0c;但是信息比较杂并不建议初学者&#xff08;主要是看不懂和打击学习兴趣&#…

使用 Nginx 提升网站访问速度

Nginx ("engine x") 是一个高性能的 HTTP 和 反向代理 服务器&#xff0c;也是一个 IMAP/POP3/SMTP 代理服务器。 Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的&#xff0c;它已经在该站点运行超过两年半了。 Igor 将源代码以类 BSD 许可证的…

网站的基本内容

简史 编辑 语音 因特网起源于美国国防部高级研究计划管理局建立的阿帕网。 [1] 阿帕网于1968年开始组建 &#xff0c;1969 年第一期工程投入使用。开始时只有4个节点。1970年的ARPANET&#xff08;阿帕网&#xff09;已初具雏形&#xff0c;并且开始向非军用部门开放&#x…