保护 Spring Boot 应用

springboot 用于保护 Spring Boot 应用,能够处理 BOOT-INF/classesBOOT-INF/lib、Spring Boot Loader 和框架扫描。

1. GUI 操作

  1. 在应用类型页面选择 Spring Boot

    选择 Spring Boot

  2. 选择要保护的 Spring Boot 应用、随包 Java 版本和目标平台,然后选择简单模式或高级模式。

    选择输入、Java 版本、目标平台和模式

  3. 使用高级模式时,按需选择输出布局、要保护的依赖 JAR、JavaFX 设置、JVM 启动选项和排除规则;简单模式会根据兼容性扫描自动确定布局和排除项。各选项的含义见 Protector4J 高级模式设置

    配置 Spring Boot 的高级参数

  4. 选择输出目录,核对参数摘要,然后点击运行保护

    选择输出目录并执行保护

2. CLI 示例

最简写法:

p4j springboot app.jar dist

默认使用 p4jx-fat 布局。要显式选择其它布局:

p4j springboot app.jar dist --layout fat
p4j springboot app.jar dist --layout separate

只保护应用的一部分:

p4j springboot app.jar dist \
  --protect 'com.example.service.impl.**' \
  --exclude 'com.example.dto.**,com.example.config.**'

3. 输出结构与布局

p4jx-fat:默认布局,单个受保护归档

dist/
├── app.p4jx              # 使用 jar 归档后缀时为 app.jar
├── vlxjre/
├── run.sh
├── run.command
└── run.bat

特点:

  • 整个应用作为单个 P4JX 归档交付;
  • 物理文件默认不是 ZIP;
  • Spring Boot 资源、嵌套依赖和元数据通过虚拟 JAR 视图提供;
  • 保护范围最广,适合不依赖第三方类路径扫描器的应用。

fat:Spring Boot 兼容布局

dist/
├── app.jar
├── app.p4jx              # 使用 jar 后缀时为 app-protected.jar
├── vlxjre/
└── run.*

特点:

  • app.jar 保留标准的 BOOT-INF 物理结构;
  • 受保护类的真实实现放在旁边的 P4JX 归档中;
  • 适合需要扫描物理 Spring Boot JAR 结构的应用,例如使用 ClassGraph 或 Reflections 的应用;
  • 两个文件相互依赖,必须一起更新、一起交付。

separate:拆分式兼容布局

dist/
├── plain-launcher.jar
├── app.p4jx
├── lib/
├── vlxjre/
└── run.*

特点:

  • Spring Boot Loader、未受保护的类和依赖三者分开存放;
  • 适合要求 lib/* 扁平类路径的老旧集成环境;
  • 受保护类由生成的启动器预加载;
  • 新项目应优先使用 p4jx-fat,或采用扫描器推荐的 p4jx-fat / fat

如何选择布局

场景推荐布局
标准的 Spring Boot 服务p4jx-fat
应用确实使用了 ClassGraph、Reflections 这类扫描器fat
需要扁平的外部依赖目录,或需要单独加密依赖文件separate
拿不准先执行 --compat-scan

ZIP 覆盖层只能帮到那些直接读取 ZIP 中央目录的工具,它无法替代 ClassLoader 和类路径扫描器所需要的物理 Spring Boot 结构。

4. 启动

./run.sh --spring.profiles.active=prod

Windows:

run.bat --spring.profiles.active=prod

不要用系统 JRE 替换输出目录中的 vlxjre

打包 Windows 目标时,还可以额外生成一个原生启动程序。三种布局都支持,它与启动脚本并存,详见生成 Windows EXE 启动器

JVM 启动选项

打包时可以固定 JVM 启动选项,既可以在 GUI 的 JVM 启动选项中每行填写一个,也可以在命令行中指定:

p4j springboot app.jar dist \
  --jvm-option -Xms1g \
  --jvm-option -Xmx2g

要为已部署的包临时追加选项:

APP_JAVA_OPTS="-Duser.timezone=Asia/Shanghai" ./run.sh

也可以直接编辑已部署的脚本:

  • macOS 与 Linux:在 run.sh 中,于生成的 JVM_OPTS=(...)JVM_OPTS+=(...) 之后加上 JVM_OPTS+=("-Xms1g" "-Xmx2g")
  • Windows:在 run.bat 中,于生成的 set "JVM_OPTS=..." 之后加上 set "JVM_OPTS=%JVM_OPTS% -Xms1g -Xmx2g"

不要删除打包器为 Spring Boot 或 JavaFX 生成的选项,例如 --add-opens 和模块路径。重新打包会覆盖所有手工改动,详见 JVM 启动选项配置

5. 保护范围

默认保护 BOOT-INF/classes 下的应用类。以下这些与 Spring 相关的类,通常保持不受保护更合适:

  • @Controller@RestController@ControllerAdvice 类;
  • @Configuration 类、自动配置类,以及经 AOT 或 CGLIB 增强的类;
  • Jackson DTO、JPA 实体、record 和校验模型;
  • 应用入口类,以及由框架直接构造或代理的类;
  • 需要在运行时做字节码增强的类。

保护服务实现,并通过公开的 facade 或接口访问它们。规则支持精确类名,以及 pkg.*pkg.**

6. 保护依赖 JAR

--protect-lib 可以保护 BOOT-INF/lib 中匹配的依赖,三种布局都支持。

p4j springboot app.jar dist \
  --protect-lib 'company-core-*.jar,pricing-*.jar'

只保护自有的闭源依赖。不要为了「多保护一点」而去加密 Spring、Tomcat、日志库、数据库驱动这类第三方框架包。

7. 兼容性扫描

p4j springboot app.jar --compat-scan
p4j springboot app.jar dist --compat-apply

这两个选项不能同时使用,它们的区别是:

选项作用何时使用
--compat-scan只扫描输入 JAR,打印风险和配置建议后退出;不做编码,也不生成 dist,因此不需要输出目录。首次保护应用、升级 Spring Boot 或其它依赖、调整保护范围或布局之后,以及排查兼容性问题时,先用它查看报告。
--compat-apply扫描后合并保守建议,然后继续编码并写出结果,因此必须指定输出目录。已经看过扫描结果并接受这些建议时,用它完成打包;规则验证过之后的重复构建和 CI 流程也适用。

springboot 来说,--compat-apply 可以根据扫描结果选择布局、追加排除规则,并调整扫描器 ZIP 覆盖层、JavaFX 和归档后缀等选项。除排除规则之外的这些选项,命令行中显式指定的值优先。建议排除的类默认会与你显式写的 --exclude 合并;如果不希望自动追加,同时传入 --no-compat-excludes 即可。扫描器只做静态启发式分析,需要修改代码才能解决的问题不会被 --compat-apply 自动修复,打包完成后仍然要在目标平台上做回归测试。

其它 CLI 命令、全部选项、环境变量和自动化示例,请参阅 CLI 参数参考