Servlet Filter going in infinite loop when FORWARD

2019-02-27 23:36发布

问题:

I have a filter defined in web.xml like following:-

<filter-mapping>
    <filter-name>AuthenticationFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>ERROR</dispatcher>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>INCLUDE</dispatcher>
</filter-mapping>
<filter>
    <display-name>AuthenticationFilter</display-name>
    <filter-name>AuthenticationFilter</filter-name>
    <filter-class>com.filters.AuthenticationFilter</filter-class>
</filter>

and In the filter I have following code:-

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  // TODO Auto-generated method stub
  // place your code here

  HttpServletRequest httpRequest = (HttpServletRequest) request;
  HttpServletResponse hres = (HttpServletResponse) response;


  String pathInfo = httpRequest.getRequestURI().trim();

  System.out.println(pathInfo);

  // Do not process any non-jsp files or LogIn.jsp  ! pathInfo.endsWith("jsf") || 
  if (pathInfo.endsWith("RegistrationForm.jsf") || pathInfo.endsWith("Login.jsf")) {
   chain.doFilter(request, response);
   return;
  }
  // pass the request along the filter chain
  User user = (User) httpRequest.getSession().getAttribute("USER_IN_SESSION");
  if(user==null)
   hres.sendRedirect("Login.jsf");
  else {
   chain.doFilter(request, response);

  }

 }

The problem is that if I invoke the app with Topic.jsp it loops over like this:-

Topic.jsp
LogIn.jsf
Login.jsp
Login.jsf
Login.jsp
...

I have found the problem is the FORWARD in mappings. and if remove this entry, it works

<dispatcher>FORWARD</dispatcher>

Please help me solve this puzzzle of infinite loop alternating .jsp & .jsf :)

回答1:

Theory:

  1. Topics.jsp requires validation, so a redirect is made to LogIn.jsf.

  2. LogIn.jsf is served by the FacesServlet. But the page that is containg the faces is really a jsp page. So the servlet mades a forward to the LogIn.jsp (the page that builds the component tree).

  3. In your filter, the path is LogIn.jsp and you don't validate a request for LogIn.jsp so you ask for authentication and a redirect to LogIn.jsf is made again. Go to step 2.

So if you remove , the forwarding of the FacesServlet from LogIn.jsf to LogIn.jsp doesn't enter in the loop.

Quick solution: Add LogIn.jsp to the list of path infos in your if statement.



回答2:

First of all, why do you want to hook on forward/include/error dispatchings as well next to the (default) global and all-covering request?

Get rid of all those <dispatcher> lines in your filter mapping. You don't need any of them for an authentication filter. The HTTP requests are the only which counts. The internal forward/include/error dispatchings can only take place when the HTTP request has already been arrived (and filtered).

Also, instead of this check on the request URI, you can also map the filter on a more specific <url-pattern> like /secured/* or so and put all pages which require a login over there and put the register and login page outside.