J2EE: deny direct jsp call

A customer of mine asked me, for a web application that all the direct jsp request will be forbidden. All except to jsp that reside in a /public/ or deeper directory.

J2EE come in our help with Filters. It’s very easy to implement.

First of all an edit to /WEB-INF/web.xml in order to tell the application that a filter is on the run. Add something like the following. Make it fit in your configuration file; for example if you have other filters (here is for a quick download JspFilter: web.xml).

<filter>
    <filter-name>JspFilter</filter-name>
    <display-name>JspFilter</display-name>
    <filter-class>path.to.filters.JspFilter</filter-class>
    <init-param>
        <param-name>forbidUrl</param-name>
        <param-value>/forbidden.jsp</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>JspFilter</filter-name>
    <url-pattern>*.jsp</url-pattern>
</filter-mapping>

What’s said here is that you have a new filter in the specified package, that should come in use for every jsp request (*.jsp) and has a parameter (forbidUrl) that specify which page should be displayed for error. You could specify even a servlet or a static html.

Create the needed jsp. In my case is /forbidden.jsp.

Now the filter class (download code).

package path.to.filters;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 *
 * Listen for every call and filter every jsp request redirecting to a forbidden page
 * if not in public (or deeper) directory.
 */
public class JspFilter implements Filter {
    private static final Log logger = LogFactory.getLog(JspFilter.class);
    private FilterConfig config = null;
    /* (non-Javadoc)
     * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
     */
    public void init(FilterConfig config) throws ServletException {
        this.config = config;
    }

    /* (non-Javadoc)
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
        logger.debug("JspFilter::doFilter()");

        HttpServletRequest http = (HttpServletRequest) request;

        //if in "/public/" directory normal chain
        if(http.getRequestURI().indexOf("/public/")>=0){
            chain.doFilter(request, response);
        }else{
            RequestDispatcher disp =  http.getRequestDispatcher(config.getInitParameter("forbidUrl"));
            disp.forward(request,response);
        }
    }

    /* (non-Javadoc)
     * @see javax.servlet.Filter#destroy()
     */
    public void destroy() {
    }

}
Advertisements

2 thoughts on “J2EE: deny direct jsp call

  1. Kishore Senji says:

    The above works but be aware that this breaks if the user sends a path parameter to the url. If the client knows the path to the hidden page, to get to the page, he just needs to add /public/ path parameter. For example, if the hidden page is /path/to/hidden.jsp, the user can just get to the page bypassing the filter by adding /public/ to the very end like so /path/to/hidden.jsp;/public/. request.getRequestURI() returns the path paramters as well and this will break your security. Be sure to parse for path parameters to enforce the security filtering.

  2. You’re right.

    You could fix it with a regex, let’s say for example ORO package, so in the Filter instead using the indexOf attribute you could use something like (I’ve not tried it) “/^.+\\/public\\/.+\\??.+/”

    I’ve improvised the regex, and can be wrong.

    Thanks for the feedback.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s