近期fastjson出现了一个漏洞,只要开启了setAutoType特性就会有风险。我在测试环境中使用的项目也不幸被波及了,这让我有些郁闷。虽然改动很小,但我一直在寻求一个解决方案,对于使用fastjson的同时又想保证安全性的问题感到困扰。我想寻找一款工具来提示我们在使用fastjson时不要打开这个特性。刚好阿里开源了p3c,这是一款代码规范检查工具,有对应的IDE插件,可以在编码过程中提示设置的规则。我决定对它进行拓展,增加对fastjson是否打开setAutoType特性的检查。
p3c主要包括三个部分:
1. PMD实现(p3c-pmd):使用PMD来实现代码规范检查。
《阿里巴巴Java开发手册》中的大部分规则都在p3c-pmd模块中实现,这也是我这次研究的主要部分。
关于PMD:
p3c使用了PMD,这是一款静态代码扫描工具。它可以检查Java代码中是否含有未使用的变量、空的抓取块、不必要的对象等。PMD使用JavaCC生成解析器来解析源代码并生成AST(抽象语法树),通过对AST的检查可以直接从源代码文本层面来对代码进行检查。
1. AST:
关于AST的介绍网上有很多,这里只简单提两点:
AST是源代码的抽象语法结构的树状表示。
抽象语法树并不依赖于原语言的语法,也就是说它和语法分析阶段所采用的上下文无关。
PMD使用JavaCC来生成AST。关于JavaCC的相关资料可以在网上查看,这里不过多介绍。
自定义规则:
PMD官方文档介绍了自定义规则的实现步骤,这里主要描述本文需要设计的步骤。
1. 定义规则集:
PMD的规则需要配置在XML文件中,新建一个XML文件来表示规则集。在规则集中引用自定义规则。
2. 配置规则:
在规则标签中对某一规则进行配置,包括提示消息和告警级别。还可以配置运行参数,通过properties和property对类属性赋值。
3. 编写规则:
规则的编写比较简单,PMD已经给我们做好了配套的开发框架和工具,只要确定规则的情境,按照固定的模式去编写即可。确定实现方式,可以使用纯Java方式实现,也可以使用XPath方式实现。
对于本文的需求,需要确定在导入ParserConfig类时,是否调用了setAutoTypeSupport方法且参数为true。当然这个条件是不够严谨的,还需要判断是否导入了ParserConfig类,也要考虑直接写全限定名的情况。但考虑到一般的写法,以及IDE的格式化处理,这样的处理已经可以满足大部分场景了。
编写规则实现类:
4. 测试规则:
PMD推荐对于每个规则,至少要有一个正向和逆向的测试用例,来验证规则出现和不出现的情况。PMD也提供了一套框架用于测试,只要按照约定好的方式添加xml测试文件即可。
对于本文的p3c-pmd模块:
在构建脚本中,我们需要配置多个Maven仓库的源地址。例如,我们可以设置一个指向Sonatype OSS仓库的Maven源,以及一个指向JetBrains的IntelliJ插件服务仓库的地址。我们还需要启用本地Maven仓库和Maven仓库。在依赖项中,我们需要引入Kotlin Gradle插件,并指定其版本号为$kotlin_version。
对于所有项目,我们将设置组名为’com.alibaba.p3c.idea’,并应用Java插件、Kotlin插件和Maven发布插件。我们将源代码兼容性设置为Java 1.8,并将Java编译选项的编码设置为UTF-8。我们还需要对所有配置应用一种解析策略,该策略将缓存更改模块的时长设置为零秒。在仓库设置中,我们将启用本地Maven仓库、jcenter仓库和Maven仓库。在依赖项中,我们将引入Kotlin标准库和JUnit测试框架。