Welcome file ignores security constraint

jsf, security-constraint, servlets, welcome-file

Solution

You are not using `<welcome-file>` entirely correctly. It should represent the sole filename of the file which needs to be served whenever a folder is been requested, irrespective of the requested folder (the root `/`, or `/public/` or `/secured/`, etc).

The welcome file is served by an internal forward as performed by `RequestDispatcher#forward()`. Internal forwards do not trigger the security constraints. You need to send a redirect instead.

Change the `<welcome-file>` to a more sane default, e.g. `index.xhtml`.

<welcome-file-list>
    <welcome-file>index.xhtml</welcome-file>
</welcome-file-list>

And create one in the webapp's root like `/index.xhtml`. If you need to redirect every request on `/index.xhtml` to `/secured/secure.xhtml`, then there are basically 2 ways:

Map a `Filter` on the URL pattern of `/index.xhtml` and call `response.sendRedirect("secured/secure.xhtml")` inside the `doFilter()` method. E.g.

@WebFilter("/index.xhtml")
public class IndexFilter implements Filter {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.sendRedirect("secured/secure.xhtml"));
    }

    // ...
}

Put a `<f:event type="preRenderView">` in the `/index.xhtml` which calls a backing bean method which in turn does a `externalContext.redirect("secured/secure.xhtml")`. E.g.

<f:event type="preRenderView" listener="#{indexBean.redirect}" />

with

@ManagedBean
@ApplicationScoped
public class IndexBean {

    public void redirect() throws IOException {
        FacesContext.getCurrentInstance().getExternalContext().redirect("secured/secure.xhtml");
    }

}

Problem

my web.xml: ``` <context-param> <param-name>javax.faces.PROJECT_STAGE</param-name> <param-value>Development</param-value> </context-param> <welcome-file-list> <welcome-file>/secured/secure.xhtml</welcome-file> </welcome-file-list> <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> <context-param> <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name> <param-value>true</param-value> </context-param> <security-constraint> <web-resource-collection> <web-resource-name>Restricted</web-resource-name> <url-pattern>/secured/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection> <auth-constraint> <role-name>ADMIN</role-name> </auth-constraint> </security-constraint> <login-config> <auth-method>FORM</auth-method> <realm-name>jdbc-realm</realm-name> <form-login-config> <form-login-page>/public/login.xhtml</form-login-page> <form-error-page>/public/error.xhtml</form-error-page> </form-login-config> </login-config> ``` I want my web app to redirect unauthorized users to login page. The funny thing i had this working but i made some stupid changes and now on accessing `localhost:8080` i always see secure.xhtml even when not logged in. `localhost:8080/secured/secure.xhtml` redirects fine.

Original source