4

Please do not close this question as answered, because all links I found like this and they are about how to block single static URL, but not a dynamic.

I have a Tomcat 7 and I have an application something like http://server/myapp/. I need to restrict some pages inside this application for some IPs. for example, everything should work fine for all IPs, except these 2 pages

http://server/myapp/admin/appversion/index.jsp http://server/myapp/admin/appversion/app_parameters.jsp

for static URL's it works perfectly if I add the filter to server's web.xml (...\apache-tomcat-7\conf\web.xml) like this

<filter>
    <filter-name>IPFilter</filter-name>
    <filter-class>org.apache.catalina.filters.RemoteAddrFilter</filter-class>
    <init-param>
        <param-name>allow</param-name>
        <param-value>127\.\d+\.\d+\.\d+</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>IPFilter</filter-name>
    <url-pattern>/admin/appversion/index.jsp</url-pattern>
    <url-pattern>/admin/appversion/app_parameters.jsp</url-pattern>
</filter-mapping>

The problem comes when I need to do dynamic (or regexp) filtering. For example, every time I have a new version of application this part of URL (appversion) changes.

/admin/appversion/app_parameters.jsp

real url today looks like this /admin/1.0/app_parameters.jsp in 1 month it will be /admin/1.1/app_parameters.jsp etc. and I do not want to change it every time when I have an update. Also it might be different for dev, test and production environment and I do not want to support 3 different configurations and change for every update.

If I try to do it like this

<url-pattern>/admin/*/app_parameters.jsp</url-pattern>

then it does not work. and if I read tomcat official documentation there is no explanation how this works. There are some examples like /*, but it works only for every page.

My question: Is there any way how to configure tomcat in a standard way and restrict some pages dynamically? One of the solutions can be to find full syntax of url-pattern and check if proper regexp is supported. Maybe using subfilters/nested filters etc. Or there is only one solution to create my custom java filter based on org.apache.catalina.filters.RemoteAddrFilter where I can apply proper regular expression to the URL?

P.S. one might think why I have admin pages inside the main application and I just should modify my app and move it to another app, but the problem is, that this application is a standard application from some vendor. I did not create this application by myself. If I change this application by my self, I will lose a support for it and I already checked, it is not easy to move this 2 pages. These 2 pages have a lot of dependencies from other parts of the application. Of course, I will create a ticket for this vendor separately, but it will be good to get an independent solution (Plan B) in case vendor cannot provide something.

UPDATE 1

I have checked tomcat source codes and looks like only 4 patterns are supported in element. This is the code from org.apache.catalina.core.ApplicationFilterFactory

private boolean matchFiltersURL(String testPath, String requestPath) {
    if (testPath == null) {
        return false;
    }
    if (testPath.equals(requestPath)) {
        return true;
    }

    if (testPath.equals("/*"))
        return true;
    if (testPath.endsWith("/*")) {
        if (testPath.regionMatches(0, requestPath, 0, testPath.length() - 2)) {
            if (requestPath.length() == testPath.length() - 2)
                return true;
            if ('/' == requestPath.charAt(testPath.length() - 2)) {
                return true;
            }
        }
        return false;
    }

    if (testPath.startsWith("*.")) {
        int slash = requestPath.lastIndexOf('/');
        int period = requestPath.lastIndexOf('.');
        if ((slash >= 0) && (period > slash) && (period != requestPath.length() - 1) && (requestPath.length() - period == testPath.length() - 1)) {

            return testPath.regionMatches(2, requestPath, period + 1, testPath.length() - 2);
        }
    }

    return false;
}

briefly what is supported

  1. exact URL match
  2. <url-pattern>/*</url-pattern> means match for all URLs.
  3. <url-pattern>/some/path/*</url-pattern> means match for all URLs starting with  "/some/path". It support /* only at the end of the URL.
  4. <url-pattern>*.ext</url-pattern> means match for any path but with specific extension.
  5. All others are not supported (examples what is not supported: /fld1/*/fld2, /fld1/*.jsp, etc

some examples which can help to understand it

matchFiltersURL("", "/fld1/fld2/mypage.jsp")
     (boolean) false

matchFiltersURL("*", "/fld1/fld2/mypage.jsp")
     (boolean) false

matchFiltersURL("/*", "/fld1/fld2/mypage.jsp")
     (boolean) true

matchFiltersURL("/fld1/*", "/fld1/fld2/mypage.jsp")
     (boolean) true

matchFiltersURL("/fld1*", "/fld1/fld2/mypage.jsp")
     (boolean) false

matchFiltersURL("/fld1/fld2/*", "/fld1/fld2/mypage.jsp")
     (boolean) true

matchFiltersURL("/fld1/*/mypage.jsp", "/fld1/fld2/mypage.jsp")
     (boolean) false

matchFiltersURL("*./fld1/fld2/mypage.jsp", "/fld1/fld2/mypage.jsp")
     (boolean) false

matchFiltersURL("*./fld1/fld2/mypagejs", "./fld1/fld2/mypagejsp")

matchFiltersURL("*.jsp", "/.jsp");
     (boolean) true

matchFiltersURL("*.xxxx", "/.xxxx");
     (boolean) true

matchFiltersURL("*./fld1/xxxx", "/fld1/.xxxx");
     (boolean) false

matchFiltersURL("*./fld1/.xxxx", "/fld1/.xxxx");
     (boolean) false

matchFiltersURL("/fld1/fld2/*.jsp", "/fld1/fld2/mypage.jsp")
     (boolean) false

matchFiltersURL("*./fld1/fld2/*", "/fld1/fld2/mypage.jsp")
     (boolean) false

As result of this, it is clearly not possible to use for dynamic filtering. The only possibility I can see now is a custom filter or nested filters.

Zlelik
  • 559
  • 1
  • 7
  • 17

0 Answers0