Tomcat支持url地址特殊字符(源代码篇)
修改原因
目前Tomcat在实际使用过程中,经常会出现漏洞,需要通过升级tomcat版本来升级补丁,解决漏洞问题。例如:
原则上来说,一般性不要涉及跨版本升级的话(7.X,8.0.X,8.5.X等),直接升级补丁(类似8.0.24升级到8.0.51这样)问题不大。
业务系统由于前期设计的问题,会出现在URL地址中传输JSON数据的现象(正常应该是通过Post,Body 的形式传输),例如:http://xxxxService?json=[test:’123’] 这种格式,而Tomcat在版本升级过程中,已经禁用中括号([,]),大括号({,})等在URL地址中的传输,所以会导致一旦升级版本,整个业务系统都会报错,其他系统如果有类似的通过URL地址传输JSON的,也会出现同样的错误。可以看下面图:
业务系统前期设计不合理,牵涉的层面比较多,改业务系统不太现实,因为安全性问题大于一切的,所以合计了以后,就通过修改tomcat源代码的形式来实现。下面案例是修改了8.5.57的源代码,也是记录下这个过程。
其实后续新的版本,已经支持通过配置文件来开放URL中的特殊字符了(连接在下面,亲测有效)。改源代码是下下策,每次版本升级都要修改下。当时51版本刚出来的时候,还不支持这么快。
源代码修改
Ant安装
下载地址: ant.apache.org/bindownload…
配置Ant环境变量
解压压缩包到指定目录,然后配置环境变量,具体过程不赘述
windows环境为例:
验证ant环境
命令提示符 ant -V
Tomcat源代码
源代码下载
源代码及部署包下载,这个就不多说了,按照需要的版本去官网下载 源代码及部署包下载地址: archive.apache.org/dist/tomcat…,然后按照目录进去下载 例如8.5.57版本 源代码地址就是:archive.apache.org/dist/tomcat…, 部署包地址就是:archive.apache.org/dist/tomcat…
解压缩源代码
创建目录及文件夹
-
源代码根目录创建 catalina-home文件夹
-
创建POM.xml文件
-
其他目录管理
-
复制根目录的conf文件夹和webapps文件夹catalina_home目录下
-
进入catalina_home目录,创建4个lib,logs,temp,work空文件夹
-
-
修改POM.xml文件,引入依赖
源代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.apache.tomcat</groupId>
<artifactId>Tomcat8.0</artifactId>
<name>Tomcat8.0</name>
<version>8.0</version>
<build>
<finalName>Tomcat8.0</finalName>
<sourceDirectory>java</sourceDirectory>
<testSourceDirectory>test</testSourceDirectory>
<resources>
<resource>
<directory>java</directory>
</resource>
</resources>
<testResources>
<testResource>
<directory>test</directory>
</testResource>
</testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3</version>
<configuration>
<encoding>UTF-8</encoding>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.4</version>
</dependency>
<dependency>
<groupId>ant</groupId>
<artifactId>ant</artifactId>
<version>1.7.0</version>
</dependency>
<dependency>
<groupId>wsdl4j</groupId>
<artifactId>wsdl4j</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>javax.xml</groupId>
<artifactId>jaxrpc</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>org.eclipse.jdt.core.compiler</groupId>
<artifactId>ecj</artifactId>
<version>4.5.1</version>
</dependency>
</dependencies>
</project>
Ant构建初始化
-
进入tomcat源代码目录
-
复制 build.properties.default --> 重命名build.properties
-
修改build.properties 文件
-
修改 base.path (自定义路径,不修改也没关系)
base.path=E:/code/tomcat8551/apache-tomcat-8.5.57-src/tomcat-build-libs
-
修改 base-maven.loc (中央仓库地址,不修改也没关系,如果无法下载可以修改成阿里云的地址)
base-maven.loc=https://repo.maven.apache.org/maven2
-
-
复制文件到base.path路径下(三个文件夹全部复制过去)
Ant构建部署
- 进入到tomcat源代码目录,执行ant命令
一般最后出现Success就代表执行成功了
中间可能会出现很多错误,什么SSL,无法解压等,这个看具体情况,具体解决
源代码运行
源代码导入IntellijIdea或者Eclipse
默认以Maven的形式导入
增加启动类
修改启动参数
-Dcatalina.home=catalina-home
-Dcatalina.base=catalina-home
-Djava.endorsed.dirs=catalina-home/endorsed
-Djava.io.tmpdir=catalina-home/temp
-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager
-Djava.util.logging.config.file=catalina-home/conf/logging.properties
-Dfile.encoding=utf-8
修改JSP解析
默认我们用Bootstrap 启动的话,是不会加载jsp解析器的,默认访问就会导致页面出错。
-
修改源代码,增加JSP解析
代码路径:
org.apache.catalina.startup.ContextConfig
修改位 置:大概778行
context.addServletContainerInitializer(new JasperInitializer(),null);
-
启动验证
解决控制台乱码
一般启动的时候,会出现如下乱码:
这个是由于properties文件中的中文是直接中文显示,没有转成unicode,但是这个错误在不同的操作系统中还不一样,有些操作系统显示是正常的。这个目前没什么好办法,如果碰到就转一下。
解决方法有两种:
修改properties中文编码格式
-
寻找显示错误的class文件
-
找到指定的获取属性的代码
-
找到指定的properties文件,一般直接全局搜索界面名称
-
转换成unicode编码
这里需要用到jdk自带的native2ascii 程序,一般JDK的环境变量设置好了,可以在任意命令提示符里执行
格式 native2ascii 源文件路径 输出文件路径 例如 native2ascii xxx/xxxx.proerties xxx/xxxx2.proerpties
然后把转换好后的内容更新到源文件里(不建议直接替换,保留副本)
- 正确输出结果
存在的问题,这类properties文件太多,一个个转换很难受,建议采用第二种直接修改源代码的方式,可以通过修改源代码解决
总共修改两个文件:
-
org.apache.tomcat.util.res.StringManager.getString
方法修改内容:
// 解决tomcat控制台乱码问题 try{ str=new String(str.getBytes("ISO-8859-1"),"UTF-8"); } catch(Exception e){ e.printStackTrace(); }
-
org.apache.jasper.compiler.Localizer.getMessage
方法修改内容:
//解决tomcat控制台乱码问题 try{ str=new String(str.getBytes("ISO-8859-1"),"UTF-8"); } catch(Exception e){ e.printStackTrace(); }
如果是GB2312就有问题,不过一般默认都是会使用UTF-8,所以默认按照UTF-8去修改就行
解决Tomcat不支持url地址传输json参数的问题
源代码修改
代码路劲: org.apache.tomcat.util.http.parser.httpParser
修改位置: 大概124行
修改内容:
String prop = System.getProperty("tomcat.util.http.parser.HttpParser.requestTargetAllow");
if (prop != null) {
// for (int i = 0; i < prop.length(); i++) {
// char c = prop.charAt(i);
// if (c == '{' || c == '}' || c == '|') {
// REQUEST_TARGET_ALLOW[c] = true;
// } else {
// log.warn(sm.getString("http.invalidRequestTargetCharacter",
// Character.valueOf(c)));
// }
// }
}
REQUEST_TARGET_ALLOW['|']=true;
REQUEST_TARGET_ALLOW['{']=true;
REQUEST_TARGET_ALLOW['}']=true;
REQUEST_TARGET_ALLOW['[']=true;
REQUEST_TARGET_ALLOW[']']=true;
编译输出
具体参考前面的 Ant编译部署
输出文件路径: 源代码/output/build/lib/tomcat-coyote.jar
tomcat更新
把tomcat-coyote.jar文件抠出来,放到tomcat的发布目录就行 tomcat路径是 tomcat/lib 目录下
tomcat-coyote.jar就是处理特殊字符的jar,只要更新这个就行了。
整个过程小问题不少,不过还是挺有学习价值的,tomcat的运行模式,代码架构等等
转载自:https://juejin.cn/post/7155779758465220645