Java使用嵌入式Tomcat时如何隐藏错误信息中的Tomcat版本号
问题描述
- 基于Java开发的应用采用嵌入式Tomcat作为服务器,初始化嵌入式Tomcat实例的基础代码如下:
Tomcat tomcat = new Tomcat()
- 服务触发异常时,默认返回的错误页面会直接展示当前使用的Tomcat版本信息,存在敏感信息泄露风险。已知可通过覆写
ServerInfo.properties文件实现版本信息隐藏,但不清楚Java项目中的具体实现方式。
实现方案
以下两种方式都可以实现版本信息隐藏,根据项目实际情况选择即可:
方案一:类路径新增配置文件覆盖默认配置
Tomcat加载服务器信息配置时,会优先读取当前项目类路径下的org/apache/catalina/util/ServerInfo.properties文件,不存在该文件时才会加载Tomcat核心jar包内置的默认配置,利用这个加载规则就可以直接覆写版本信息:
- 在项目资源目录(Maven/Gradle项目对应
src/main/resources目录)下,逐层创建目录结构org/apache/catalina/util/ - 在新建的util目录下创建
ServerInfo.properties文件,写入自定义配置替换默认版本字段:
server.info=Web Server server.number= server.built=
- 重新打包启动服务后,错误页、响应Server头中携带的Tomcat真实版本号就会被替换为自定义内容,不会再泄露版本信息。
方案二:启动时通过反射动态修改版本信息
如果不想新增额外配置文件,可以在初始化Tomcat实例之前,通过反射直接修改ServerInfo类的内置字段,跳过配置文件加载逻辑:
- 在Tomcat实例初始化代码前,增加如下反射逻辑,注意要在
new Tomcat()执行前调用:
import org.apache.catalina.util.ServerInfo; import java.lang.reflect.Field; public class TomcatConfig { private static void maskTomcatVersion() throws NoSuchFieldException, IllegalAccessException { // 修改服务信息字段 Field infoField = ServerInfo.class.getDeclaredField("serverInfo"); infoField.setAccessible(true); infoField.set(null, "Web Server"); // 清空版本号字段 Field numberField = ServerInfo.class.getDeclaredField("serverNumber"); numberField.setAccessible(true); numberField.set(null, ""); // 清空构建时间字段 Field builtField = ServerInfo.class.getDeclaredField("serverBuilt"); builtField.setAccessible(true); builtField.set(null, ""); } public static void main(String[] args) throws Exception { // 先执行版本掩码 maskTomcatVersion(); // 再初始化Tomcat实例 Tomcat tomcat = new Tomcat(); // 后续其他Tomcat配置逻辑 } }
额外加固建议
隐藏版本信息的同时,建议配置全局自定义错误页,替换Tomcat默认错误页,进一步避免其他服务信息泄露:
// 假设已经创建了Web应用上下文Context ctx ErrorPage globalErrorPage = new ErrorPage(); globalErrorPage.setLocation("/custom-error.html"); // 覆盖常见错误码 globalErrorPage.addErrorCode(400); globalErrorPage.addErrorCode(404); globalErrorPage.addErrorCode(500); globalErrorPage.addErrorCode(503); ctx.addErrorPage(globalErrorPage);
内容的提问来源于stack exchange,提问作者Sachin Naik
相关产品推荐
相关产品推荐

