配置tomcat限制指定IP地址訪問后端應用


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 &quot;%r&quot; %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;
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM