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.