编译修改tomcat7源码,支持同时设置允许ip和域名

前言

tomcat中有两个valve,RemoteHostValve 和 RemoteAddrValve,但是这两个同时使用会有问题(也可能是我不会用)。因为我希望在所有地方用域名可以访问,但是只有在公司内才能用ip访问。所以它的配置无法实现我的想法。于是想到了自己修改源码后编译即可。

下载

所有文件下载地址:http://pan.baidu.com/s/1dDv2Ewp
1. 下载 tomcat7 源码(需要jdk1.6,高低都不行)
2. 下载安装 jdk1.6 (我的是mac,坑啊,好难找,文后会有下载地址)
3. 下载 ant

配置

  1. 解压tomcat7源码到目录
  2. 解压ant到目录
  3. 安装jdk,jdk1.6在所有平台都是双击运行(运行安装),如果此前你有其它版本的jdk,请注意修改好环境变量。
  4. 把ant目录下的bin目录添加到环境变量path中,linux例:export PATH=$PATH:/usr/local/ant-1.9.6/bin
  5. 进入到tomcat7源码,复制一份build.properties.default到 build.properties,修改其中的 base.path=/usr/share/java 为一个有权限修改的目录(linux 和 mac 下可能无权限读写)
  6. 修改了环境变量记得 source /etc/profile 一下,以使生效。
  7. 在tomcat源码目录下 运行 ant,结果如下:
Buildfile: /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/build.xml

build-prepare:
   [delete] Deleting directory /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/temp
   [delete] Deleting directory /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/work
    [mkdir] Created dir: /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/temp

download-compile:

testexist:
     [echo] Testing  for /Users/yiboliu/IdeaProjects/java/tomcat-native-1.1.33/tomcat-native.tar.gz

downloadfile-2:

proxyflags:

setproxy:

testexist:
     [echo] Testing  for /Users/yiboliu/IdeaProjects/java/commons-daemon-1.0.15/commons-daemon-1.0.15.jar

downloadgz-2:

testexist:
     [echo] Testing  for /Users/yiboliu/IdeaProjects/java/commons-daemon-1.0.15/commons-daemon-1.0.15-native-src.tar.gz

downloadfile-2:

proxyflags:

setproxy:

testexist:
     [echo] Testing  for /Users/yiboliu/IdeaProjects/java/commons-pool-1.5.7-src/build.xml

downloadgz-2:

proxyflags:

setproxy:

testexist:
     [echo] Testing  for /Users/yiboliu/IdeaProjects/java/commons-dbcp-1.4-src/build.xml

downloadgz-2:

build-prepare:
   [delete] Deleting directory /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/temp
    [mkdir] Created dir: /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/temp

build-manifests:

build-tomcat-dbcp:

testexist:
     [echo] Testing  for /Users/yiboliu/IdeaProjects/java/ecj-4.4.2/ecj-4.4.2.jar

downloadfile-2:

compile-prepare:

download-validate:

validate:

compile-java6:

guess-java7:

check-java7:

compile-java7:

compile:

build-manifests:

package-java7:

package:

build-docs:
     [xslt] Transforming into /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/webapps/docs
     [xslt] Transforming into /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/webapps/docs/appdev
     [xslt] Transforming into /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/webapps/docs/funcspecs
     [xslt] Transforming into /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/webapps/docs/config
     [xslt] Transforming into /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/webapps/docs/architecture
     [xslt] Transforming into /Users/yiboliu/IdeaProjects/apache-tomcat-7.0.65-src/output/build/webapps/docs/tribes

compile-webapp-examples:

deploy:

examples-sources:
     [echo] Building Tomcat JDBC pool libraries

prepare:

download:

build-src:

build:

BUILD SUCCESSFUL
Total time: 2 seconds

说明运行编译成功,编译好的tomcat在 ./output/build/ 下面。

可能的问题

jdk版本问题

错误日志

BUILD FAILED build.xml:2361: The following error occurred while executing this line:
BUILD FAILED build.xml:2449: Compile failed; see the compiler error output for details.
error: DelegatingPreparedStatement is not abstract and does not override abstract method isCloseOnCompletion()

如上,如果遇到类没有实现什么方法,但是它又不是一个抽象类云云的问题,基本可以确定是jdk版本,修改环境变量为1.6版本的即可。

没遇到其它问题

  • 无内容

修改源码

这才是本文的重点

复制RemoteHostValve类为新的类

此类用于既能够匹配host,也能匹配address。
内容如下:

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.catalina.valves;


import org.apache.catalina.connector.Request;
import org.apache.catalina.connector.Response;

import javax.servlet.ServletException;
import java.io.IOException;


/**
 * Concrete implementation of <code>RequestFilterValve</code> that filters
 * based on the remote client's host name optionally combined with the
 * server connector port number.
 *
 * @author yibo.liu
 */

public final class RemoteHostAddrValve
        extends RequestFilterValve {


    // ----------------------------------------------------- Instance Variables


    /**
     * The descriptive information related to this implementation.
     */
    private static final String info =
            "org.apache.catalina.valves.RemoteHostAddrValve/1.0";


    /**
     * Flag deciding whether we add the server connector port to the property
     * compared in the filtering method. The port will be appended
     * using a ";" as a separator.
     */
    protected volatile boolean addConnectorPort = false;


    // ------------------------------------------------------------- Properties


    /**
     * Return descriptive information about this Valve implementation.
     */
    @Override
    public String getInfo() {

        return (info);

    }


    /**
     * Get the flag deciding whether we add the server connector port to the
     * property compared in the filtering method. The port will be appended
     * using a ";" as a separator.
     */
    public boolean getAddConnectorPort() {
        return addConnectorPort;
    }


    /**
     * Set the flag deciding whether we add the server connector port to the
     * property compared in the filtering method. The port will be appended
     * using a ";" as a separator.
     *
     * @param addConnectorPort The new flag
     */
    public void setAddConnectorPort(boolean addConnectorPort) {
        this.addConnectorPort = addConnectorPort;
    }


    // --------------------------------------------------------- Public Methods


    /**
     * Extract the desired request property, and pass it (along with the
     * specified request and response objects) to the protected
     * <code>process()</code> method to perform the actual filtering.
     * This method must be implemented by a concrete subclass.
     *
     * @param request  The servlet request to be processed
     * @param response The servlet response to be created
     * @throws IOException      if an input/output error occurs
     * @throws ServletException if a servlet error occurs
     */
    @Override
    public void invoke(Request request, Response response)
            throws IOException, ServletException {

        String host;
        if (addConnectorPort) {
            host = request.getRequest().getRemoteHost() + ";" + request.getConnector().getPort();
        } else {
            host = request.getRequest().getRemoteHost();
        }
        String addr = request.getRequest().getRemoteAddr();
        process(host, addr, request, response);

    }

    /**
     * {@link #process(String, Request, Response)}
     *
     * @param host
     * @param addr
     * @param request
     * @param response
     * @throws IOException
     * @throws ServletException
     */
    protected void process(String host, String addr, Request request, Response response)
            throws IOException, ServletException {

        if (isAllowed(host)) {
            getNext().invoke(request, response);
            return;
        } else if (isAllowed(addr)) {
            getNext().invoke(request, response);
            return;
        }

        // Deny this request
        denyRequest(request, response);

    }

}

说明

在 invoke 方法中同时获取 host 和 address ,传给新的方法 process ,此方法来自于父类,但是稍作修改。

添加配置

在文件 mbeans-descriptors.xml 中,找到 RemoteHostValve ,将其配置文件复制一份,并修改新的类名为 RemoteHostAddrValve 即可。

再编译

在命令行中,进入tomcat 源码目录,执行 ant。 编译成功后,即可测试。

测试

在./output/build/conf/server.xml 中的Host 里面添加

这里的ip是我本地ip地址,域名是我在hosts文件中配置的域名,这里没有使用 localhost 和 127.0.0.1,目的是为了让它们两个不能访问。

运行 ./output/build/bin/startup.sh 启动 tomcat ,即可看到结果,10.0.0.137:8080 和 test.test.com:8080 均可访问,但是 localhost:8080 和 127.0.0.1:8080 却不可以,测试成功。

另注

如果 request.getRemoteHost() 不能获取到域名,请检查tomcat配置文件,server.xml 中的 Connector 连接中是否设置了 enableLookups,此值应该设置为 true ,因为即为 true ,设置为 false 时,只能获取到 ip地址,不能获取到 域名信息。

<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               enableLookups="true"
               redirectPort="8443" />
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值