3

I have configured my application to use OmniFaces's Extensionless URLs feature, but now that I enabled security in my web.xml, the extensionless requests do not get caught by the <security-constraint>.

web.xml

<!-- JSF configuration -->

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>
<context-param>
    <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
    <param-value>true</param-value>
</context-param>
<context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
</context-param>

<!-- OmniFaces configuration -->

<context-param>
    <param-name>org.omnifaces.FACES_VIEWS_SCAN_PATHS</param-name>
    <param-value>/*.xhtml</param-value>
</context-param>

<!-- Servlets and filters. -->

<servlet>
    <servlet-name>facesServlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>facesServlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
</servlet-mapping>

<!-- Welcome files, error pages and mime types. -->

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

<!-- Security constraints -->

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Allowed resources</web-resource-name>
        <url-pattern>/javax.faces.resource/*</url-pattern>
    </web-resource-collection>
</security-constraint>
<security-constraint>
    <display-name>SSL transport</display-name>
    <web-resource-collection>
        <web-resource-name>Secure Area</web-resource-name>
        <url-pattern>/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
        <role-name>ADMINISTRATOR</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

<!-- Security roles -->

<security-role>
    <role-name>ADMINISTRATOR</role-name>
</security-role>

<!-- Login config -->

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>myRealm</realm-name>
    <form-login-config>
        <form-login-page>/login.xhtml</form-login-page>
        <form-error-page>/login.xhtml</form-error-page>
    </form-login-config>
</login-config>

login.xhtml

<h:form>
    <h:panelGrid columns="1">
        <h:outputText value="Username:" />
        <h:inputText id="username" required="true"
            value="#{appSession.loginUsername}"
            requiredMessage="Username is required" />
        <h:message for="username" />
        <hr />

        <h:outputText value="Password:" />
        <h:inputSecret id="password" required="true"
            value="#{appSession.loginPassword}"
            requiredMessage="Password is required" />
        <h:message for="password" />

        <h:commandButton value="Login" action="#{appSession.login}" />
    </h:panelGrid>

    <h:messages globalOnly="true" showDetail="false" />
</h:form>

AppSession.java

@SessionScoped
@ManagedBean
public class AppSession {

    private String loginUsername;
    private String loginPassword;

    public AppSession() {   }

    public String login() {
        try {
            Faces.login(loginUsername, loginPassword);

            return "index.xhtml?faces-redirect=true";
        } catch (ServletException e) {
            e.printStackTrace();

            return "login.xhtml";
        }
    }

    public void logout() throws IOException {
        Faces.invalidateSession();
        Faces.redirect("index.xhtml");
    }

    //Getters and setters

}

So, if I browse to index.xhtml, it gets redirected correctly to login. However if I browse to index, there is no redirect and the browser is allowed to download the content from index. I know that this is exactly what is specified in web.xml by <url-pattern>*.xhtml</url-pattern>, but how can I configure the application, so that extensionless URLs get also restricted by login?

If I try this with <url-pattern>/*</url-pattern> under <security-constraint>, it gets redirected successfully, however my login form does not work in this case. I have to do programmatic login with JSF, since I want to reuse the credentials for webservices. Any ideas so I get a valid configuration?

I am using OmniFaces 2.0, Mojarra 2.2.7 on GlassFish 4.1.

Daniel Szalay
  • 4,041
  • 12
  • 57
  • 103
  • The `/*` should work. I've pinged Arjan on this. – BalusC Feb 06 '15 at 15:04
  • I am redirected successfully to the login page (using `/*.xhtml`), when a page from a secure area is attempted without having an extension. (Inside ``, I am using directory level mappings (thus not extension mappings) such as `/xxx_yyy_zzz/*`. Using OmniFaces 1.8.1, JSF 2.3.0-m01, GlassFish 4.1, PrimeFaces 5.1). (I however, get an exception while redirecting to a home page after successful login which is a special case associated with my application only and still to be debugged. Thus, it was not taken into account) – Tiny Feb 06 '15 at 16:00
  • Upgraded the library OmniFaces 1.8.1 to OmniFaces 2.0 and the result is the same as the preceding comment. – Tiny Feb 06 '15 at 17:49
  • @BalusC Extended the question so there is more info about the case. – Daniel Szalay Feb 09 '15 at 08:52
  • Can you clarify "login form does not work" in developer's perspective? – BalusC Feb 09 '15 at 08:59
  • @BalusC When the application is opened, I get redirected to `/login`. If I hit submit, the page is reloaded, but `#{appSession.login}` is definitely not triggered. Sounds like `facesServlet` is not kicking in (it is set to `*.xhtml`). I have tried to disable the Extensionless URLs feature, and the login worked again from `/login.xhtml`. – Daniel Szalay Feb 09 '15 at 09:59
  • @BalusC SSCCE (Eclipse project): https://dl.dropboxusercontent.com/u/14670704/OmniExtensionlessLogin.zip – Daniel Szalay Feb 09 '15 at 10:49
  • I very quickly glanced at your SSCCE, but noticed several things like 2 templates, the `FullAjaxExceptionHandler` in faces-config.xml, a few `styleClass` attributes, a lot of options in web.xml like `javax.faces.FACELETS_REFRESH_PERIOD` and even the PrimeFaces 'FileUploadFilter'. Are all of those really necessary to reproduce the problem? I.e. since you included the Ajax exception handler in the SSCCE, does that mean everything works if you omit that one? And same question for the PrimeFaces filter, why did you include it? Does everything work without it? – Arjan Tijms Feb 09 '15 at 22:57
  • @ArjanTijms You are right, I didn't take _short_ seriously enough :) I have removed the things you mentioned and updated the SSCCE (still available @ above link. The symptoms still exist. – Daniel Szalay Feb 10 '15 at 07:46
  • It appears that you're mixing container managed login and programmatic login. – BalusC Feb 10 '15 at 08:48
  • @BalusC Can you clarify this; You mean because of `j_username`, `j_password`? I have changed those and still have the problem. Also updated the SSCCE. – Daniel Szalay Feb 10 '15 at 09:47
  • @DanielSzalay I think BalusC refers to this: http://stackoverflow.com/questions/21546511/get-j-username-in-j-security-check-jsf-2-0 if you use Servlet's FORM your /login page needs to post to "j_security_check", you are posting back to /login and then logging in programmatically. – dexter meyers Feb 10 '15 at 14:41

1 Answers1

2

The problem is fixed if I add login and login.xhtml to allowed resources:

    <web-resource-collection>
        <web-resource-name>Allowed resources</web-resource-name>
        <url-pattern>/javax.faces.resource/*</url-pattern>
        <url-pattern>/login.xhtml</url-pattern>
        <url-pattern>/login</url-pattern>
    </web-resource-collection>
Daniel Szalay
  • 4,041
  • 12
  • 57
  • 103