likes
comments
collection
share

Tomcat支持url地址特殊字符(源代码篇)

作者站长头像
站长
· 阅读数 11

修改原因

  目前Tomcat在实际使用过程中,经常会出现漏洞,需要通过升级tomcat版本来升级补丁,解决漏洞问题。例如:

Tomcat支持url地址特殊字符(源代码篇)

  原则上来说,一般性不要涉及跨版本升级的话(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支持url地址特殊字符(源代码篇)

业务系统前期设计不合理,牵涉的层面比较多,改业务系统不太现实,因为安全性问题大于一切的,所以合计了以后,就通过修改tomcat源代码的形式来实现。下面案例是修改了8.5.57的源代码,也是记录下这个过程。

其实后续新的版本,已经支持通过配置文件来开放URL中的特殊字符了(连接在下面,亲测有效)。改源代码是下下策,每次版本升级都要修改下。当时51版本刚出来的时候,还不支持这么快。

Tomcat支持url地址中的特殊字符(配置篇)

源代码修改

Ant安装

下载地址: ant.apache.org/bindownload…

Tomcat支持url地址特殊字符(源代码篇)

配置Ant环境变量

解压压缩包到指定目录,然后配置环境变量,具体过程不赘述

windows环境为例:


Tomcat支持url地址特殊字符(源代码篇)


Tomcat支持url地址特殊字符(源代码篇)


Tomcat支持url地址特殊字符(源代码篇)

验证ant环境

命令提示符 ant -V Tomcat支持url地址特殊字符(源代码篇)

Tomcat源代码

源代码下载

源代码及部署包下载,这个就不多说了,按照需要的版本去官网下载 源代码及部署包下载地址: archive.apache.org/dist/tomcat…,然后按照目录进去下载 例如8.5.57版本 源代码地址就是:archive.apache.org/dist/tomcat…, 部署包地址就是:archive.apache.org/dist/tomcat…

解压缩源代码

Tomcat支持url地址特殊字符(源代码篇)

创建目录及文件夹

  1. 源代码根目录创建 catalina-home文件夹

    Tomcat支持url地址特殊字符(源代码篇)

  2. 创建POM.xml文件

    Tomcat支持url地址特殊字符(源代码篇)

  3. 其他目录管理

    1. 复制根目录的conf文件夹和webapps文件夹catalina_home目录下 Tomcat支持url地址特殊字符(源代码篇)

    2. 进入catalina_home目录,创建4个lib,logs,temp,work空文件夹 Tomcat支持url地址特殊字符(源代码篇)

  4. 修改POM.xml文件,引入依赖

    Tomcat支持url地址特殊字符(源代码篇)

源代码

<?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构建初始化

  1. 进入tomcat源代码目录

  2. 复制 build.properties.default --> 重命名build.properties

  3. 修改build.properties 文件

    • 修改 base.path (自定义路径,不修改也没关系) Tomcat支持url地址特殊字符(源代码篇)

      base.path=E:/code/tomcat8551/apache-tomcat-8.5.57-src/tomcat-build-libs
      
    • 修改 base-maven.loc (中央仓库地址,不修改也没关系,如果无法下载可以修改成阿里云的地址) Tomcat支持url地址特殊字符(源代码篇)

      base-maven.loc=https://repo.maven.apache.org/maven2
      
  4. 复制文件到base.path路径下(三个文件夹全部复制过去)

    Tomcat支持url地址特殊字符(源代码篇)

Ant构建部署

  1. 进入到tomcat源代码目录,执行ant命令

Tomcat支持url地址特殊字符(源代码篇)

一般最后出现Success就代表执行成功了

中间可能会出现很多错误,什么SSL,无法解压等,这个看具体情况,具体解决

源代码运行

源代码导入IntellijIdea或者Eclipse

默认以Maven的形式导入

Tomcat支持url地址特殊字符(源代码篇)

增加启动类

Tomcat支持url地址特殊字符(源代码篇)

修改启动参数
-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

Tomcat支持url地址特殊字符(源代码篇)

修改JSP解析

    默认我们用Bootstrap 启动的话,是不会加载jsp解析器的,默认访问就会导致页面出错。

Tomcat支持url地址特殊字符(源代码篇)

  • 修改源代码,增加JSP解析

    代码路径: org.apache.catalina.startup.ContextConfig 修改位 置:大概778行

    Tomcat支持url地址特殊字符(源代码篇)

    context.addServletContainerInitializer(new JasperInitializer(),null);
    
  • 启动验证

    Tomcat支持url地址特殊字符(源代码篇)

解决控制台乱码

    一般启动的时候,会出现如下乱码:

Tomcat支持url地址特殊字符(源代码篇)

    这个是由于properties文件中的中文是直接中文显示,没有转成unicode,但是这个错误在不同的操作系统中还不一样,有些操作系统显示是正常的。这个目前没什么好办法,如果碰到就转一下。

解决方法有两种:

修改properties中文编码格式

  1. 寻找显示错误的class文件

    Tomcat支持url地址特殊字符(源代码篇)

  2. 找到指定的获取属性的代码

    Tomcat支持url地址特殊字符(源代码篇)

  3. 找到指定的properties文件,一般直接全局搜索界面名称 Tomcat支持url地址特殊字符(源代码篇)

  4. 转换成unicode编码

    这里需要用到jdk自带的native2ascii 程序,一般JDK的环境变量设置好了,可以在任意命令提示符里执行

格式 native2ascii 源文件路径 输出文件路径 例如 native2ascii xxx/xxxx.proerties xxx/xxxx2.proerpties

Tomcat支持url地址特殊字符(源代码篇)

然后把转换好后的内容更新到源文件里(不建议直接替换,保留副本)

Tomcat支持url地址特殊字符(源代码篇)

  1. 正确输出结果

Tomcat支持url地址特殊字符(源代码篇)

存在的问题,这类properties文件太多,一个个转换很难受,建议采用第二种直接修改源代码的方式,可以通过修改源代码解决

总共修改两个文件:

  • org.apache.tomcat.util.res.StringManager.getString 方法

    Tomcat支持url地址特殊字符(源代码篇)

    修改内容: Tomcat支持url地址特殊字符(源代码篇)

    // 解决tomcat控制台乱码问题
    try{
        str=new String(str.getBytes("ISO-8859-1"),"UTF-8");
    }
    catch(Exception e){
        e.printStackTrace();
    }
    
  • org.apache.jasper.compiler.Localizer.getMessage 方法

    Tomcat支持url地址特殊字符(源代码篇)

    修改内容:

    Tomcat支持url地址特殊字符(源代码篇)

    //解决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行

Tomcat支持url地址特殊字符(源代码篇)

修改内容:

Tomcat支持url地址特殊字符(源代码篇)

        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支持url地址特殊字符(源代码篇)

tomcat更新

把tomcat-coyote.jar文件抠出来,放到tomcat的发布目录就行 tomcat路径是 tomcat/lib 目录下

tomcat-coyote.jar就是处理特殊字符的jar,只要更新这个就行了。

整个过程小问题不少,不过还是挺有学习价值的,tomcat的运行模式,代码架构等等