Naman
Naman

Reputation: 129

How to Invoke Servlet and Filter in sequence

hi I am working on one web application and facing issue while invoking servelets mentioned in web.xml.

Here is my web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">

     <servlet>
            <servlet-name>FileServlet</servlet-name>
            <servlet-class>com.tpg.fileserver.FileServlet</servlet-class>
     </servlet>
    <servlet-mapping>
            <servlet-name>FileServlet</servlet-name>
            <url-pattern>/*</url-pattern>
        </servlet-mapping>
    <filter>
            <filter-name>AuthorizationFilter</filter-name>
            <filter-class>com.tpg.fileserver.AuthorizationFilter</filter-class>
      </filter>
      <filter-mapping>
            <filter-name>AuthorizationFilter</filter-name>
            <url-pattern>/*</url-pattern>
      </filter-mapping>

  </web-app>

The issue is that when i m trying to run my application I want the Authroization Filter to run first and then The File Servelet. Right now what is happening is the reverse of what i want. I also tried using 0 for File Servelet but that didnt helped.Below mentioned is my Filter Class code.

public class AuthorizationFilter implements Filter  {

    private static final String kNotAuthorizedUrl = "/NotAuthorized.html";
    private static final String kTrustedHostsFileName = "trusted_hosts.txt";
    private static final String kPublicFilesFileName = "public_files.txt";

    private static final String TRUSTED_HOSTS = "TRUSTED_HOSTS";
    private static final String PUBLIC_FILES = "PUBLIC_FILES";
    private static Properties itsProperties = null;
    public static final String kPropertySingleSignOnURL = "sso-url";
    private static final String kPropertiesFileName = "metadata.properties";
    private static boolean itsInitialized = false;

    private static synchronized void initialize() {
        if (!itsInitialized) {
            try {
                ProductMetadataAPI.setProduct(Version.kProductName, Version.kPhysical);
                System.out.println("Inside Initialize");
                PersistenceAPI.isDebugging = true;
                JNDIConnectionFactory connFactory = new JNDIConnectionFactory("DataSource"); // IDB

                SingleSignOnAuthenticator.setAuthenticationUrl(ConfigurationUtils.getProperties().getProperty(kPropertySingleSignOnURL));

                SecurityAPI.setSecurity(
                    SecurityAPI.makeSecurity(
                        new StandardFactory(),
                        new PersistenceRepository(connFactory),
                        new CommonsBase64Codec(),
                        new SingleSignOnAuthenticator()));

                itsInitialized = true;
            } catch (Throwable e) {
                LoggerClass.logErr(e);
            }
        }
    }

    private void requestAuthentication(HttpServletResponse response) {
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.addHeader("WWW-Authenticate", "BASIC Realm=\"Single Sign-on\"");
        LoggerClass.logInfoMsg("SSO not set. redirecting to siteminder......");
    }


    public void doFilter(ServletRequest inRequest, ServletResponse inResponse, FilterChain chain) throws IOException, ServletException {
        try {
            HttpServletRequest request = (HttpServletRequest) inRequest;
            HttpServletResponse response = (HttpServletResponse) inResponse;
            System.out.println("Before Setting Serervlet Context");
            ConfigurationUtils.setCurrentServletContext(request.getSession().getServletContext());
            System.out.println("After Setting Serervlet Context");
            initialize();

            if (request instanceof HttpServletRequest && (request.getMethod().equals("GET") || request.getMethod().equals("POST"))) {
                String remoteHost = "", authorization = "", userName = "", password = "";
                HttpServletRequest r = (HttpServletRequest)request;
                Enumeration<String> e = r.getHeaderNames();
                while (e.hasMoreElements()) {
                    String headerName = e.nextElement();
                    LoggerClass.logInfoMsg(headerName + "=" + r.getHeader(headerName));
                }
                LoggerClass.logDebugMsg("Proxy-Client-IP is :" + r.getHeader("Proxy-Client-IP"));
                LoggerClass.logDebugMsg("Remote-Address-IP is :" + r.getRemoteAddr());


                remoteHost = r.getHeader("Proxy-Client-IP");
                if (remoteHost == null) {
                    remoteHost = r.getRemoteAddr();
                    LoggerClass.logDebugMsg("Remote-Address-IP ["+remoteHost + "] is requesting " + r.getRequestURI());
                }else{
                    LoggerClass.logDebugMsg("Proxy-Client-IP ["+remoteHost + "] is requesting " + r.getRequestURI());
                }

                authorization = r.getHeader("Authorization");
                if (authorization != null) {
                    final int index = authorization.indexOf(' ');
                    if (index > 0) {
                        final String[] credentials = StringUtils.split(new String(Base64.decodeBase64(authorization.substring(index))), ':');

                        if (credentials.length == 2) {
                            userName = credentials[0].toUpperCase();
                            password = credentials[1];
                        }
                    }
                }

                if (isSiteminderAuthenticationPresent(r)) {
                    LoggerClass.logInfoMsg("Inside Siteminder Logic ......");
                    chain.doFilter(request, response);
                    return;
                } else if (isPublic(request) || isTrusted(remoteHost)) {
                    LoggerClass.logInfoMsg("Inside Public/Trusted Host Logic ......");
                    chain.doFilter(request, response);
                    return;
                } else if (!isBasicAuthenticationPresent(userName, password)) {
                    LoggerClass.logInfoMsg("Failed in Basic Authentication Present.....");
                    requestAuthentication(response);
                } else if (!isBasicAuthenticationValid(r.getSession(), userName, password)) {
                    LoggerClass.logInfoMsg("Failed in Basic Authentication Validation.....");
                    requestAuthentication(response);
                } else {
                    chain.doFilter(request, response);
                }
            }
            response.sendRedirect(request.getContextPath() + kNotAuthorizedUrl);
        } catch (Exception e) {
            LoggerClass.logErr(e);
            throw new RuntimeException(e);
        }
    }
}

Below mentioned is my Servlet Partial Code :

public class FileServlet extends HttpServlet
{
public FileServlet()
    {
         System.out.println("In fileServlet");
         this.itsRootDir = Common.getRequiredProperty(Common.kPropertyRootDir);
            // some business logic
    }
@Override public void doGet(HttpServletRequest inRequest, HttpServletResponse inResponse)
    throws ServletException, IOException
    {
        String theRelFileName = Common.extractFileName(inRequest, false);
        String theFileName = this.itsRootDir + theRelFileName;
        File theFile = new File(theFileName);
     //Some more Business Logic
}
}           

Below present are the Sysout logs I got in application logs. Here I noticed one strange thing. First the call is going to File Servlet, Then Authorization Filter and then again to File Servlet.

[8/8/14 0:54:05:109 EDT] 0000002b SystemOut     O In fileServlet
[8/8/14 0:54:05:161 EDT] 0000002b SystemOut     O In Authoriazation Filter
[8/8/14 0:54:05:232 EDT] 0000002b SystemOut     O In fileServlet

Upvotes: 3

Views: 5343

Answers (2)

Naman
Naman

Reputation: 129

The answer for the above mentioned issue was that the constructor present in FileServlet was invoking before the filter was executed. To solve this problem I have changed the constructor to a public method which is being called in doget() method of Servlet. After this changed the filter was invoking first and then the servlet was being invoked.

Upvotes: 0

SparkOn
SparkOn

Reputation: 8946

The filters are always initialized during webapp's startup in the order as they are definied in web.xml.

The servlets are by default initialized during the first HTTP request on their url-pattern only.

So in this case first The webapp's web.xml will be parsed and every Filter found in web.xml will be created once and kept in server's memory

Now when a request comes from url pattern like /* the container looks for the pattern finds the mapping for servlet so initializes the servlet. Then to process the request the filter gets invoked.

To solve this you can change the url pattern of servlet.When the user enters some url pattern like /* redirect to filter class and if he authenticates successfully then redirect to servlet specified with some other url pattern or else redirect to error page

Upvotes: 1

Related Questions