i'm looking for a way to write a programm wich should intercept all browser's post and get requests.
The program should filter these requests and search for some resources. I want to forbit access to these resources.
It should be a kind of parental control.
I have:
apache tomcad;
java.
P.S. Sorry for my english, i know it's not perfect=)
Thanks.
Remark: the program should be a desktop appleication.
Try with a Filter. Here a short description about it.
A filter is an object that performs filtering tasks on either the request to a resource (a servlet or static content), or on the response from a resource, or both.
Examples that have been identified for this design are:
Authentication Filters
Logging and Auditing Filters
Image conversion Filters
Data compression Filters
Encryption Filters
Tokenizing Filters
Filters that trigger resource access events
XSL/T filters
Mime-type chain Filter
Sample code:
web.xml:
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.x.y.z.servlet.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
MyFilter.java:
public class MyFilter implements Filter {
#Override
public void init(FilterConfig filterConfig) throws ServletException {
// read init-parameter from web.xml
}
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String uri = httpServletRequest.getRequestURI();
// do what you want to do based on uri
// call below method to propagate it to next servet/jsp/filter in the chain
// filterChain.doFilter(servletRequest, servletResponse);
}
#Override
public void destroy() {
}
}
Related
I'm trying to call a filter by passing parameters to be validated before calling my servlet. But, the request parameters are passing as null. While the same parameters are being received in my servlet. I'm not able to figure it out what could be the reason.
My call of servlet will be using window.open from Javascript.
Here is my code
window.open ("http://localhost:8080/SEMS/testAdd?yearFormat=yyyy", "hiddenFrame");
My filter
public class CBFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public CBFilter() {}
public void destroy() {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
String yearFormat= request.getParameter("yearFormat");
System.out.println("[Filter] Year Format : "+yearFormat);
chain.doFilter(request, response);
}
}
Web.xml
<filter>
<display-name>CBFilter</display-name>
<filter-name>CBFilter</filter-name>
<filter-class>com.cb.CBFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CBFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
The same request parameter is available in servlet.
Try casting the ServletRequest to HttpServletRequest like so:
HttpServletRequest req = (HttpServletRequest)request;
String yearFormat= req.getParameter("yearFormat");
..see if that helps
I want some concrete filter to be applied for all urls except for one concrete (i.e. for /* except for /specialpath).
Is there a possibility to do that?
sample code:
<filter>
<filter-name>SomeFilter</filter-name>
<filter-class>org.somproject.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SomeFilter</filter-name>
<url-pattern>/*</url-pattern> <!-- the question is: how to modify this line? -->
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
The standard Servlet API doesn't support this facility. You may want either to use a rewrite-URL filter for this like Tuckey's one (which is much similar Apache HTTPD's mod_rewrite), or to add a check in the doFilter() method of the Filter listening on /*.
String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
chain.doFilter(request, response); // Just continue chain.
} else {
// Do your business stuff here for all paths other than /specialpath.
}
You can if necessary specify the paths-to-be-ignored as an init-param of the filter so that you can control it in the web.xml anyway. You can get it in the filter as follows:
private String pathToBeIgnored;
public void init(FilterConfig config) {
pathToBeIgnored = config.getInitParameter("pathToBeIgnored");
}
If the filter is part of 3rd party API and thus you can't modify it, then map it on a more specific url-pattern, e.g. /otherfilterpath/* and create a new filter on /* which forwards to the path matching the 3rd party filter.
String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
chain.doFilter(request, response); // Just continue chain.
} else {
request.getRequestDispatcher("/otherfilterpath" + path).forward(request, response);
}
To avoid that this filter will call itself in an infinite loop you need to let it listen (dispatch) on REQUEST only and the 3rd party filter on FORWARD only.
See also:
How to prevent static resources from being handled by front controller servlet which is mapped on /*
How to handle static content in Spring MVC?
I used an approach described by Eric Daugherty: I created a special servlet that always answers with 403 code and put its mapping before the general one.
Mapping fragment:
<servlet>
<servlet-name>generalServlet</servlet-name>
<servlet-class>project.servlet.GeneralServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>specialServlet</servlet-name>
<servlet-class>project.servlet.SpecialServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>specialServlet</servlet-name>
<url-pattern>/resources/restricted/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>generalServlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
And the servlet class:
public class SpecialServlet extends HttpServlet {
public SpecialServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
}
This approach works when you want to prevent a certain filter and all the following ones. It should work well if you eg. want to serve some content as static resources within your servlet container instead of letting your application logic (through a filter like GuiceFilter):
Map the folder with your static resource files to the default servlet. Create a servlet filter and put it before the GuiceFilter in your web.xml. In your created filter, you can separate between forwarding some requests to the GuiceFilter and others directly to the dispatcher. Example follows...
web.xml
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>StaticResourceFilter</filter-name>
<filter-class>com.project.filter.StaticResourceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>StaticResourceFilter</filter-name>
<url-pattern>/static/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
StaticResourceFilter.class
public class StaticResourceFilter implements Filter {
private final static Logger LOGGER = LoggerFactory.getLogger(StaticResourceFilter.class);
private static final String RESOURCE_PATH = "/static/";
#Override
public void init(final FilterConfig filterConfig) throws ServletException {
LOGGER.info("StaticResourceFilter initialized");
}
#Override
public void doFilter(final ServletRequest request, final ServletResponse response,
final FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getServletPath();
if (path.toLowerCase().startsWith(RESOURCE_PATH)) {
request.getRequestDispatcher(path).forward(request, response);
} else {
chain.doFilter(request, response);
}
}
#Override
public void destroy() {
LOGGER.info("StaticResourceFilter destroyed");
}
}
Unfortunately if you just want to skip a single step in the filter chain while keeping those that follows, this will not work.
I don't think you can, the only other configuration alternative is to enumerate the paths that you want to be filtered, so instead of /* you could add some for /this/* and /that/* etc, but that won't lead to a sufficient solution when you have alot of those paths.
What you can do is add a parameter to the filter providing an expression (like a regular expression) which is used to skip the filter functionality for the paths matched.
The servlet container will still call your filter for those url's but you will have better control over the configuration.
Edit
Now that you mention you have no control over the filter, what you could do is either inherit from that filter calling super methods in its methods except when the url path you want to skip is present and follow the filter chain like #BalusC proposed, or build a filter which instantiates your filter and delegates under the same circumstances. In both cases the filter parameters would include both the expression parameter you add and those of the filter you inherit from or delegate to.
The advantage of building a delegating filter (a wrapper) is that you can add the filter class of the wrapped filter as parameter and reuse it in other situations like this one.
I also Had to filter based on the URL pattern(/{servicename}/api/stats/)in java code .
if (path.startsWith("/{servicename}/api/statistics/")) {
validatingAuthToken(((HttpServletRequest) request).getHeader("auth_token"));
filterChain.doFilter(request, response);
}
But its bizarre, that servlet doesn't support url pattern other than (/*), This should be a very common case for servlet API's !
I have encounterd the same issue, but I find a anwser showing below.
web.xml
<!-- set this param value for the filter-->
<init-param>
<param-name>freePages</param-name>
<param-value>
MainFrame.jsp;
</param-value>
</init-param>
filter.java
strFreePages = config.getInitParameter("freePages"); //get the exclue pattern from config file
isFreePage(strRequestPage) //decide the exclude path
this way you don't have to harass the concrete Filter class.
If for any reason you cannot change the original filter mapping ("/*" in my case) and you are dispatching to an unchangeable third-party filter, you can find useful the following:
Intercept the path to be bypassed
Skip to and execute the last ring of the filter chain (the servlet itself)
The skipping is done via reflection, inspecting the container instances in debug mode
The following works in Weblogic 12.1.3:
import org.apache.commons.lang3.reflect.FieldUtils;
import javax.servlet.Filter;
[...]
#Override
public void doFilter(ServletRequest request, ServletRespons response, FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getRequestURI();
if(!bypassSWA(path)){
swpFilterHandler.doFilter(request, response, chain);
} else {
try {
((Filter) (FieldUtils.readField(
(FieldUtils.readField(
(FieldUtils.readField(chain, "filters", true)), "last", true)), "item", true)))
.doFilter(request, response, chain);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
I was able to handle this in Spring 2 as following
private boolean isInPath(ServletRequest request) {
String PATH_TO_VALIDATE = "/path/";
String path = ((HttpServletRequest) request).getRequestURI();
return path != null && path.toLowerCase().contains(PATH_TO_VALIDATE);
}
I want some concrete filter to be applied for all urls except for one concrete (i.e. for /* except for /specialpath).
Is there a possibility to do that?
sample code:
<filter>
<filter-name>SomeFilter</filter-name>
<filter-class>org.somproject.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SomeFilter</filter-name>
<url-pattern>/*</url-pattern> <!-- the question is: how to modify this line? -->
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
The standard Servlet API doesn't support this facility. You may want either to use a rewrite-URL filter for this like Tuckey's one (which is much similar Apache HTTPD's mod_rewrite), or to add a check in the doFilter() method of the Filter listening on /*.
String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
chain.doFilter(request, response); // Just continue chain.
} else {
// Do your business stuff here for all paths other than /specialpath.
}
You can if necessary specify the paths-to-be-ignored as an init-param of the filter so that you can control it in the web.xml anyway. You can get it in the filter as follows:
private String pathToBeIgnored;
public void init(FilterConfig config) {
pathToBeIgnored = config.getInitParameter("pathToBeIgnored");
}
If the filter is part of 3rd party API and thus you can't modify it, then map it on a more specific url-pattern, e.g. /otherfilterpath/* and create a new filter on /* which forwards to the path matching the 3rd party filter.
String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
chain.doFilter(request, response); // Just continue chain.
} else {
request.getRequestDispatcher("/otherfilterpath" + path).forward(request, response);
}
To avoid that this filter will call itself in an infinite loop you need to let it listen (dispatch) on REQUEST only and the 3rd party filter on FORWARD only.
See also:
How to prevent static resources from being handled by front controller servlet which is mapped on /*
How to handle static content in Spring MVC?
I used an approach described by Eric Daugherty: I created a special servlet that always answers with 403 code and put its mapping before the general one.
Mapping fragment:
<servlet>
<servlet-name>generalServlet</servlet-name>
<servlet-class>project.servlet.GeneralServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>specialServlet</servlet-name>
<servlet-class>project.servlet.SpecialServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>specialServlet</servlet-name>
<url-pattern>/resources/restricted/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>generalServlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
And the servlet class:
public class SpecialServlet extends HttpServlet {
public SpecialServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
}
This approach works when you want to prevent a certain filter and all the following ones. It should work well if you eg. want to serve some content as static resources within your servlet container instead of letting your application logic (through a filter like GuiceFilter):
Map the folder with your static resource files to the default servlet. Create a servlet filter and put it before the GuiceFilter in your web.xml. In your created filter, you can separate between forwarding some requests to the GuiceFilter and others directly to the dispatcher. Example follows...
web.xml
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>StaticResourceFilter</filter-name>
<filter-class>com.project.filter.StaticResourceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>StaticResourceFilter</filter-name>
<url-pattern>/static/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
StaticResourceFilter.class
public class StaticResourceFilter implements Filter {
private final static Logger LOGGER = LoggerFactory.getLogger(StaticResourceFilter.class);
private static final String RESOURCE_PATH = "/static/";
#Override
public void init(final FilterConfig filterConfig) throws ServletException {
LOGGER.info("StaticResourceFilter initialized");
}
#Override
public void doFilter(final ServletRequest request, final ServletResponse response,
final FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getServletPath();
if (path.toLowerCase().startsWith(RESOURCE_PATH)) {
request.getRequestDispatcher(path).forward(request, response);
} else {
chain.doFilter(request, response);
}
}
#Override
public void destroy() {
LOGGER.info("StaticResourceFilter destroyed");
}
}
Unfortunately if you just want to skip a single step in the filter chain while keeping those that follows, this will not work.
I don't think you can, the only other configuration alternative is to enumerate the paths that you want to be filtered, so instead of /* you could add some for /this/* and /that/* etc, but that won't lead to a sufficient solution when you have alot of those paths.
What you can do is add a parameter to the filter providing an expression (like a regular expression) which is used to skip the filter functionality for the paths matched.
The servlet container will still call your filter for those url's but you will have better control over the configuration.
Edit
Now that you mention you have no control over the filter, what you could do is either inherit from that filter calling super methods in its methods except when the url path you want to skip is present and follow the filter chain like #BalusC proposed, or build a filter which instantiates your filter and delegates under the same circumstances. In both cases the filter parameters would include both the expression parameter you add and those of the filter you inherit from or delegate to.
The advantage of building a delegating filter (a wrapper) is that you can add the filter class of the wrapped filter as parameter and reuse it in other situations like this one.
I also Had to filter based on the URL pattern(/{servicename}/api/stats/)in java code .
if (path.startsWith("/{servicename}/api/statistics/")) {
validatingAuthToken(((HttpServletRequest) request).getHeader("auth_token"));
filterChain.doFilter(request, response);
}
But its bizarre, that servlet doesn't support url pattern other than (/*), This should be a very common case for servlet API's !
I have encounterd the same issue, but I find a anwser showing below.
web.xml
<!-- set this param value for the filter-->
<init-param>
<param-name>freePages</param-name>
<param-value>
MainFrame.jsp;
</param-value>
</init-param>
filter.java
strFreePages = config.getInitParameter("freePages"); //get the exclue pattern from config file
isFreePage(strRequestPage) //decide the exclude path
this way you don't have to harass the concrete Filter class.
If for any reason you cannot change the original filter mapping ("/*" in my case) and you are dispatching to an unchangeable third-party filter, you can find useful the following:
Intercept the path to be bypassed
Skip to and execute the last ring of the filter chain (the servlet itself)
The skipping is done via reflection, inspecting the container instances in debug mode
The following works in Weblogic 12.1.3:
import org.apache.commons.lang3.reflect.FieldUtils;
import javax.servlet.Filter;
[...]
#Override
public void doFilter(ServletRequest request, ServletRespons response, FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getRequestURI();
if(!bypassSWA(path)){
swpFilterHandler.doFilter(request, response, chain);
} else {
try {
((Filter) (FieldUtils.readField(
(FieldUtils.readField(
(FieldUtils.readField(chain, "filters", true)), "last", true)), "item", true)))
.doFilter(request, response, chain);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
I was able to handle this in Spring 2 as following
private boolean isInPath(ServletRequest request) {
String PATH_TO_VALIDATE = "/path/";
String path = ((HttpServletRequest) request).getRequestURI();
return path != null && path.toLowerCase().contains(PATH_TO_VALIDATE);
}
To avoid re-developing the wheel. Are there any example Java EE servlet filters that take care of some basic security checks/ i.e.
Block web requests for a time period if a rootkit hits the server, ie with a url that ends in .exe or contains "../../.."
Throttle or block IP's that are making unexpectedly high number of requests.
I also wonder if something equivalent to a Thread.sleep(1000); in the servlet filter for those particular types of requests wouldn't be such a bad thing.
Maybe this will help.
public class SuspiciousURLFilter implements Filter {
#Override
public void destroy() {
}
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
if (requestURI.endsWith(".exe")) {
HttpServletResponse httpResponse = (HttpServletResponse) response;
//send error or maybe redirect to some error page
httpResponse.sendError(HttpServletResponse.SC_BAD_REQUEST);
}
filterChain.doFilter(request, response);
}
#Override
public void init(FilterConfig config) throws ServletException {
}
}
In your web.xml:
<filter>
<filter-name>suspiciousURLFilter </filter-name>
<filter-class>your.package.SuspiciousURLFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SuspiciousURLFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
I want some concrete filter to be applied for all urls except for one concrete (i.e. for /* except for /specialpath).
Is there a possibility to do that?
sample code:
<filter>
<filter-name>SomeFilter</filter-name>
<filter-class>org.somproject.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>SomeFilter</filter-name>
<url-pattern>/*</url-pattern> <!-- the question is: how to modify this line? -->
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
The standard Servlet API doesn't support this facility. You may want either to use a rewrite-URL filter for this like Tuckey's one (which is much similar Apache HTTPD's mod_rewrite), or to add a check in the doFilter() method of the Filter listening on /*.
String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
chain.doFilter(request, response); // Just continue chain.
} else {
// Do your business stuff here for all paths other than /specialpath.
}
You can if necessary specify the paths-to-be-ignored as an init-param of the filter so that you can control it in the web.xml anyway. You can get it in the filter as follows:
private String pathToBeIgnored;
public void init(FilterConfig config) {
pathToBeIgnored = config.getInitParameter("pathToBeIgnored");
}
If the filter is part of 3rd party API and thus you can't modify it, then map it on a more specific url-pattern, e.g. /otherfilterpath/* and create a new filter on /* which forwards to the path matching the 3rd party filter.
String path = ((HttpServletRequest) request).getRequestURI();
if (path.startsWith("/specialpath/")) {
chain.doFilter(request, response); // Just continue chain.
} else {
request.getRequestDispatcher("/otherfilterpath" + path).forward(request, response);
}
To avoid that this filter will call itself in an infinite loop you need to let it listen (dispatch) on REQUEST only and the 3rd party filter on FORWARD only.
See also:
How to prevent static resources from being handled by front controller servlet which is mapped on /*
How to handle static content in Spring MVC?
I used an approach described by Eric Daugherty: I created a special servlet that always answers with 403 code and put its mapping before the general one.
Mapping fragment:
<servlet>
<servlet-name>generalServlet</servlet-name>
<servlet-class>project.servlet.GeneralServlet</servlet-class>
</servlet>
<servlet>
<servlet-name>specialServlet</servlet-name>
<servlet-class>project.servlet.SpecialServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>specialServlet</servlet-name>
<url-pattern>/resources/restricted/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>generalServlet</servlet-name>
<url-pattern>/resources/*</url-pattern>
</servlet-mapping>
And the servlet class:
public class SpecialServlet extends HttpServlet {
public SpecialServlet() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.sendError(HttpServletResponse.SC_FORBIDDEN);
}
}
This approach works when you want to prevent a certain filter and all the following ones. It should work well if you eg. want to serve some content as static resources within your servlet container instead of letting your application logic (through a filter like GuiceFilter):
Map the folder with your static resource files to the default servlet. Create a servlet filter and put it before the GuiceFilter in your web.xml. In your created filter, you can separate between forwarding some requests to the GuiceFilter and others directly to the dispatcher. Example follows...
web.xml
<servlet-mapping>
<servlet-name>default</servlet-name>
<url-pattern>/static/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>StaticResourceFilter</filter-name>
<filter-class>com.project.filter.StaticResourceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>StaticResourceFilter</filter-name>
<url-pattern>/static/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>guiceFilter</filter-name>
<filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>guiceFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
StaticResourceFilter.class
public class StaticResourceFilter implements Filter {
private final static Logger LOGGER = LoggerFactory.getLogger(StaticResourceFilter.class);
private static final String RESOURCE_PATH = "/static/";
#Override
public void init(final FilterConfig filterConfig) throws ServletException {
LOGGER.info("StaticResourceFilter initialized");
}
#Override
public void doFilter(final ServletRequest request, final ServletResponse response,
final FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getServletPath();
if (path.toLowerCase().startsWith(RESOURCE_PATH)) {
request.getRequestDispatcher(path).forward(request, response);
} else {
chain.doFilter(request, response);
}
}
#Override
public void destroy() {
LOGGER.info("StaticResourceFilter destroyed");
}
}
Unfortunately if you just want to skip a single step in the filter chain while keeping those that follows, this will not work.
I don't think you can, the only other configuration alternative is to enumerate the paths that you want to be filtered, so instead of /* you could add some for /this/* and /that/* etc, but that won't lead to a sufficient solution when you have alot of those paths.
What you can do is add a parameter to the filter providing an expression (like a regular expression) which is used to skip the filter functionality for the paths matched.
The servlet container will still call your filter for those url's but you will have better control over the configuration.
Edit
Now that you mention you have no control over the filter, what you could do is either inherit from that filter calling super methods in its methods except when the url path you want to skip is present and follow the filter chain like #BalusC proposed, or build a filter which instantiates your filter and delegates under the same circumstances. In both cases the filter parameters would include both the expression parameter you add and those of the filter you inherit from or delegate to.
The advantage of building a delegating filter (a wrapper) is that you can add the filter class of the wrapped filter as parameter and reuse it in other situations like this one.
I also Had to filter based on the URL pattern(/{servicename}/api/stats/)in java code .
if (path.startsWith("/{servicename}/api/statistics/")) {
validatingAuthToken(((HttpServletRequest) request).getHeader("auth_token"));
filterChain.doFilter(request, response);
}
But its bizarre, that servlet doesn't support url pattern other than (/*), This should be a very common case for servlet API's !
I have encounterd the same issue, but I find a anwser showing below.
web.xml
<!-- set this param value for the filter-->
<init-param>
<param-name>freePages</param-name>
<param-value>
MainFrame.jsp;
</param-value>
</init-param>
filter.java
strFreePages = config.getInitParameter("freePages"); //get the exclue pattern from config file
isFreePage(strRequestPage) //decide the exclude path
this way you don't have to harass the concrete Filter class.
If for any reason you cannot change the original filter mapping ("/*" in my case) and you are dispatching to an unchangeable third-party filter, you can find useful the following:
Intercept the path to be bypassed
Skip to and execute the last ring of the filter chain (the servlet itself)
The skipping is done via reflection, inspecting the container instances in debug mode
The following works in Weblogic 12.1.3:
import org.apache.commons.lang3.reflect.FieldUtils;
import javax.servlet.Filter;
[...]
#Override
public void doFilter(ServletRequest request, ServletRespons response, FilterChain chain) throws IOException, ServletException {
String path = ((HttpServletRequest) request).getRequestURI();
if(!bypassSWA(path)){
swpFilterHandler.doFilter(request, response, chain);
} else {
try {
((Filter) (FieldUtils.readField(
(FieldUtils.readField(
(FieldUtils.readField(chain, "filters", true)), "last", true)), "item", true)))
.doFilter(request, response, chain);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
I was able to handle this in Spring 2 as following
private boolean isInPath(ServletRequest request) {
String PATH_TO_VALIDATE = "/path/";
String path = ((HttpServletRequest) request).getRequestURI();
return path != null && path.toLowerCase().contains(PATH_TO_VALIDATE);
}