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

配置tomcat限制指定IP地址访问后端应用

2017-04-21 12:53 405 查看


1. 场景
后端存在N个tomcat实例,前端通过nginx反向代理和负载均衡。

tomcat1 tomcatN
| |
| |
-----------------
|
nginx

2. 需求
为了保护后端应用,tomcat实例只允许前端nginx服务器IP访问,其他任何地址的访问都被拒绝。



3. 实现
编辑${TOMCAT_HOME}/conf/server.xml,添加org.apache.catalina.valves.RemoteAddrValve配置,如下所示:

<Host name="localhost"  appBase="webapps"
unpackWARs="true" autoDeploy="true">

<!-- SingleSignOn valve, share authentication between web applications
Documentation at: /docs/config/valve.html -->
<!--
<Valve className="org.apache.catalina.authenticator.SingleSignOn" />
-->

<!-- Access log processes all example.
Documentation at: /docs/config/valve.html
Note: The pattern used is equivalent to using pattern="common" -->
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log." suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />

<!-- 限制指定IP地址访问Tomcat -->
<Valve className="org.apache.catalina.valves.RemoteAddrValve"
allow="127.0.0.1"
deny=""/>
</Host>


4. 原理

(1)概述
在tomcat中存在一个与容器关联的组件Valve,该组件用于处理request请求。源码注释为:



详见tomcat请求处理时序图:http://tomcat.apache.org/tomcat-8.5-doc/architecture/requestProcess/request-process.png
因此,我们可以通过添加指定Valve实现,用于在处理request请求时实现相应功能。
例如:在这里通过在<Host>元素中添加org.apache.catalina.valves.RemoteAddrValve实现限制指定IP地址访问应用程序。

(2)Valve类图



(3)源码解读

org.apache.catalina.valves.RemoteAddrValve实现Valve处理request请求接口:

@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
String property;
if (addConnectorPort) {
property = request.getRequest().getRemoteAddr() + ";" + request.getConnector().getPort();
} else {
property = request.getRequest().getRemoteAddr();
}
process(property, request, response);
}


org.apache.catalina.valves.RequestFilterValve process实现:

protected void process(String property, Request request, Response response)
throws IOException, ServletException {

if (isAllowed(property)) {
getNext().invoke(request, response);
return;
}

if (getLog().isDebugEnabled()) {
getLog().debug(sm.getString("requestFilterValve.deny",
request.getRequestURI(), property));
}

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


public boolean isAllowed(String property) {
// Use local copies for thread safety
Pattern deny = this.deny;
Pattern allow = this.allow;

// Check the deny patterns, if any
if (deny != null && deny.matcher(property).matches()) {
return false;
}

// Check the allow patterns, if any
if (allow != null && allow.matcher(property).matches()) {
return true;
}

// Allow if denies specified but not allows
if (deny != null && allow == null) {
return true;
}

// Deny this request
return false;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: