2

I have read numerous examples though I seem to have an 'exact' copy of them, so I cannot figure out why my filter will execute when I navigate to /login instead of /restricted/*. I have tried both annotations (as in the example below) and XML to define the WebFilter.

The Webfilter

@WebFilter(filterName = "AuthenticationFilter", servletNames = { "Faces Servlet" }, urlPatterns = { "/restricted/*" } )
public class AuthenticationFilter implements Filter {
    @Inject
    private SessionManager sessionManager;

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {
        System.out.println("Active AuthenticationFilter");
        if (sessionManager.getUser() == null) {
            ((HttpServletResponse) response).sendRedirect("/login");
        }
        else {
            chain.doFilter(request, response);
        }
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    @Override
    public void destroy() {
    }
}

web.xml

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>   
<filter>
    <filter-name>Pretty Filter</filter-name>
    <filter-class>com.ocpsoft.pretty.PrettyFilter</filter-class>
    <async-supported>true</async-supported>
</filter>
<filter-mapping> 
    <filter-name>Pretty Filter</filter-name> 
    <url-pattern>/*</url-pattern> 
    <dispatcher>FORWARD</dispatcher> 
    <dispatcher>REQUEST</dispatcher> 
    <dispatcher>ERROR</dispatcher>
    <dispatcher>ASYNC</dispatcher>
</filter-mapping>
<filter>
    <filter-name>NoCacheFilter</filter-name>
    <filter-class>filter.NoCacheFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>NoCacheFilter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
    <filter-name>AuthenticationFilter</filter-name>
    <filter-class>filter.AuthenticationFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>AuthenticationFilter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/restricted/*</url-pattern>
</filter-mapping>

Note

Even though the filter is defined in both files, I can assure I am not using both notations at the same time. For the sake of testing and reviewing I however did post them both.

I am new to the use of webfilters, and could not find much about using multiple filters. But what I did read, you can use multiple and they will execute in the order you defined them in web.xml.

Question

Does anyone have a clue as to why my filter will execute on pages as /login too? The app is running on Glassfish 3.1.2.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Menno
  • 12,175
  • 14
  • 56
  • 88

1 Answers1

7

The <filter-mapping> matching conditions are not inclusive, they are exclusive.

With the following mapping

<filter-mapping>
    <filter-name>AuthenticationFilter</filter-name>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/restricted/*</url-pattern>
</filter-mapping>

you're basically instructing that the filter should be invoked whenever the FacesServlet is to be invoked or whenever the URL pattern matches /restricted/*.

This is not an "and" condition as you seemed to expect. Just remove the <servlet-name> entry.

The proper @WebFilter declaration would then be

@WebFilter("/restricted/*")

assuming that you don't need a <filter-mapping> (if the order is irrelevant, for example).

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Ah ok, I will give it a try. I indeed expected this "and" situation because I saw many examples in which there was defined a servlet name. I'll report my findings after testing it. – Menno Oct 22 '12 at 21:11
  • Filters can also perfectly be mapped on specific servlets. That's usually easier as a single servlet may in turn be mapped on multiple URL patterns (e.g. some webapps map `FacesServlet` on `/faces/*`, `*.faces` and `*.jsf`; it'd be tedious to repeat those patterns in the filter mapping as well). – BalusC Oct 22 '12 at 21:13
  • Well, to be honest. I am not that far to be experimenting with the Servlets. But I'm getting there, another challenge for soon. Back on topic, your solution works, and I seem to have had it working before, but I misinterpreted another fault (my Pretty Filter redirects `/account` to `/restricted/account` so expected a hit on `/restricted/*` as this filter comes after Pretty Filter, but this is due to being the same request, isn't it?). – Menno Oct 22 '12 at 21:24
  • You're welcome. As to learning servlets, I recommend to start at our `[servlets]` tag wiki page (which I've mainly written myself): http://stackoverflow.com/tags/servlets/info – BalusC Oct 22 '12 at 21:27