您的位置:首页 > 运维架构 > Tomcat

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

2015-11-17 11:31 411 查看

前言

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

下载

所有文件下载地址:http://pan.baidu.com/s/1dDv2Ewp

1. 下载 tomcat7 源码(需要jdk1.6,高低都不行)

2. 下载安装 jdk1.6 (我的是mac,坑啊,好难找,文后会有下载地址)

3. 下载 ant

配置

解压tomcat7源码到目录

解压ant到目录

安装jdk,jdk1.6在所有平台都是双击运行(运行安装),如果此前你有其它版本的jdk,请注意修改好环境变量。

把ant目录下的bin目录添加到环境变量path中,linux例:export PATH=$PATH:/usr/local/ant-1.9.6/bin

进入到tomcat7源码,复制一份build.properties.default到 build.properties,修改其中的 base.path=/usr/share/java 为一个有权限修改的目录(linux 和 mac 下可能无权限读写)

修改了环境变量记得 source /etc/profile 一下,以使生效。

在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" />
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: