保护 Tomcat Web 应用

tomcat 把 WAR 转换为一个自包含的 Tomcat base。运行时使用编码器内置的 Tomcat 组件,不读取用户本机的 Tomcat 安装。

1. GUI 操作

  1. 在应用类型页面选择 Tomcat WAR

    选择 Tomcat WAR

  2. 选择输入 WAR、随包 Java 版本和目标平台,并选择简单模式或高级模式。

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

  3. 使用高级模式时,选择 Tomcat 9/10.1 或保持自动检测,并按需设置 Context Path、JVM 参数和排除规则;简单模式会通过兼容性扫描建议 Tomcat 版本。各选项含义见 Protector4J 高级模式设置

    配置 Tomcat 版本、Context Path 和排除规则

  4. 选择输出目录,复核参数摘要,然后点击 Run protection

    选择输出目录并执行保护

2. CLI 示例

指定 Context Path:

p4j tomcat app.war dist --context /app

兼容性扫描与自动应用建议:

p4j tomcat app.war --compat-scan
p4j tomcat app.war dist --compat-apply --context /app

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

选项行为何时使用
--compat-scan只扫描输入 WAR,打印风险和配置建议后退出;不编码、不生成 dist,因此不需要输出目录首次保护应用、升级 Tomcat 相关依赖、调整保护范围或 JSP 配置后,以及排查兼容性问题时,先用它查看报告
--compat-apply扫描后自动合并保守建议,然后继续编码并生成输出,因此必须指定输出目录已阅读扫描结果并接受自动建议时,用它完成打包;也可用于已验证过规则的重复构建或 CI 流程

tomcat--compat-apply 可根据扫描结果追加排除类,并调整 Tomcat 版本、ZIP overlay 和归档后缀等选项。对后三类选项,命令行中显式指定的值优先;建议的排除类则默认与显式 --exclude 合并。如不希望自动追加排除类,可同时传入 --no-compat-excludes。扫描器只做静态启发式分析,需要修改代码的问题不会被 --compat-apply 自动修复,生成后仍需在目标平台回归测试。

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

--tomcat-version 默认为 auto。必要时可显式指定 910.1

p4j tomcat app.war dist --context /app --tomcat-version 10.1

3. 输出结构

dist/
├── bin/
│   ├── catalina.sh
│   ├── startup.sh
│   ├── shutdown.sh
│   └── *.bat
├── conf/p4jx/
│   ├── contexts.list
│   ├── protected-classes.list
│   └── allowed-prefixes.list
├── protected/
│   └── app.p4jx
├── lib/
│   ├── p4jx-tomcat-runtime.jar
│   └── tomcat-runtime-deps.jar
├── vlxjre/
├── run.sh
└── run.bat

默认不生成物理 WAR。web.xml、静态资源、公开类、元数据桩和保护实现都位于 protected/<context>.p4jx,由 P4JX WebResourceSet 呈现给 Tomcat。

4. 启动与停止

前台运行:

./run.sh

Tomcat 风格后台启动:

./bin/startup.sh
./bin/shutdown.sh

Windows 使用对应 .bat 文件。日志写入输出目录的 logs/

JVM 启动参数

打包时可在 GUI 的 JVM startup options 中每行填写一个参数,或使用 CLI:

p4j tomcat app.war dist \
  --context /app \
  --jvm-option -Xms1g \
  --jvm-option -Xmx2g

部署后直接修改:

  • macOS/Linux:编辑 bin/catalina.sh,在 run_java() 内的 JVM_OPTS=(...) 后增加 JVM_OPTS+=("-Xms1g" "-Xmx2g"),前台和 startup.sh 后台启动都会生效。
  • Windows 前台:编辑 bin\catalina.bat,在原 set "JVM_OPTS=..." 后增加 set "JVM_OPTS=%JVM_OPTS% -Xms1g -Xmx2g"
  • Windows 后台:在 bin\startup.bat 调用 catalina.bat 之前增加 set "APP_JAVA_OPTS=-Xms1g -Xmx2g"。若需前后台共用一套持久参数,推荐通过 GUI/CLI 重新生成。

临时启动也可在命令前设置 APP_JAVA_OPTS。完整的 CMD、PowerShell 和脚本示例见 JVM 启动参数配置

5. Tomcat 版本选择

WAR API 命名空间TomcatJava 要求
javax.servlet.*Tomcat 9Java 8/11/17/21/25
jakarta.servlet.*Tomcat 10.1Java 11/17/21/25

自动检测优先从应用类和部署描述符识别 API 命名空间,依赖 JAR 名称仅作为辅助证据。检测到 javaxjakarta 混用时,工具会拒绝自动猜测。

6. JSP

WAR 含 JSP 时,默认自动在编码阶段预编译为 servlet 类和 URL 映射。原因是运行时动态 JSP 编译会从 Tomcat 工作目录定义新类,不符合保护运行时的类定义边界。

可显式控制:

--precompile-jsp
--no-precompile-jsp

生产环境建议保持默认自动预编译。禁用后,含 JSP 的应用可能在访问页面时失败。

7. 保护范围与排除规则

默认保护 WEB-INF/classes 下的应用类,WEB-INF/lib 依赖默认不保护。可排除 Web-facing 类:

p4j tomcat app.war dist \
  --context /app \
  --exclude 'com.example.web.**,com.example.dto.**'

重点排除 servlet/filter/listener、DTO、配置、实体、JNI 桥接类和需要由容器增强的类。兼容性扫描会提供保守建议。

8. 在同一 Tomcat 包中增加应用

p4j tomcat second.war dist \
  --append-app \
  --context /second

约束:

  • context path 不能与已有应用重复;
  • 新旧应用必须使用相同 Tomcat 主版本、Java 版本和目标平台;
  • 未传 --append-app 时,工具拒绝写入已有 Tomcat 包;
  • GUI 中勾选“Append application to an existing Tomcat folder”,并直接选择现有目录。

9. Java 8 注意事项

Java 8 目标会自动启用 ZIP overlay,使 Tomcat WebResourceSet 可以打开受保护归档。