0

I have a sample project configured with JAAS, JSF-2 and Primefaces. 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"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    <display-name>JAASProject</display-name>
    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
    <context-param>
        <param-name>primefaces.THEME</param-name>
        <param-value>start</param-value>
    </context-param>
    <context-param>
        <param-name>primefaces.SUBMIT</param-name>
        <param-value>partial</param-value>
    </context-param>
    <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.STATE_SAVING_METHOD</param-name>
        <param-value>client</param-value>
    </context-param>
    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>resources.application</param-value>
    </context-param>
    <listener>
        <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
    </listener>
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>Protected Area</web-resource-name>
            <url-pattern>/app/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>*</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>adbADRealm</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>
    <security-role>
        <role-name>*</role-name>
    </security-role>
    <session-config>
        <session-timeout>1</session-timeout>
    </session-config>
</web-app>

I have set <session-timeout> for testing purpose. The welcome file index.jsp is:

<%
    response.sendRedirect("app/home.xhtml");
%>

So that when I am browsing localhost:8080/JAASProject I am navigating to the login page, but the URL remains localhost:8080/JAASProject/app/home.xhtml. I guess it is desired. In login.xhtml I have:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui"
    xmlns:f="http://java.sun.com/jsf/core">

<h:head>
    <title>Login</title>
</h:head>
<h:body>
    <h:form>
        <h:panelGrid columns="2" cellpadding="5">
            <p:outputLabel value="Username" />
            <p:inputText value="#{authenticationController.username}" required="true"/>
            <p:outputLabel value="Password" />
            <p:password value="#{authenticationController.password}" required="true"/>
            <f:facet name="footer">
                <p:commandButton id="loginButton" actionListener="#{authenticationController.login}" value="Login"/>
            </f:facet>
        </h:panelGrid>
    </h:form>
</h:body>
</html>

And the AuthenticationController is:

package com.myself.jassproject.controller;

import java.io.Serializable;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;

@ManagedBean(name = "authenticationController")
@ViewScoped
public class AuthenticationController implements Serializable{

    private static final long serialVersionUID = 7083052321396088714L;

    private String originalURL;

    private String username;
    private String password;

    public AuthenticationController() {

    }

    @PostConstruct
    public void initialize() {
        ExternalContext externalContext = getExternalContext();
        originalURL = (String) externalContext.getRequestMap().get(RequestDispatcher.FORWARD_REQUEST_URI);

        if (originalURL == null) {
            originalURL = externalContext.getRequestContextPath() + "/app/home.xhtml";
        }

        System.out.println(originalURL);
    }

    public void login(ActionEvent event){
        System.out.println("==");
        try {
            getServletRequest().login(username, password);
            getExternalContext().redirect(originalURL);
        } catch (Exception ex) {
            ex.printStackTrace();
        }       
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    private ExternalContext getExternalContext() {
        return getFacesContext().getExternalContext();
    }

    private FacesContext getFacesContext() {
        return FacesContext.getCurrentInstance();
    }

    private HttpServletRequest getServletRequest() {
        return (HttpServletRequest) getExternalContext().getRequest();
    }
}

The authentication is working and I am getting navigated to the home. In home I have three buttons: one Primesfaces', one JSF's (non-ajax) and one JSF's (ajax-enabled).

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:p="http://primefaces.org/ui">

    <h:head>
        <title>Home</title>
    </h:head>
    <h:body>
        <h:form>
            <p:commandButton value="Click me (Primefaces)" actionListener="#{homeController.doSomething}"/>
            <h:commandButton value="Click me (JSF)" actionListener="#{homeController.doSomething}" />
            <h:commandButton value="Click me (JSF - AJAX)" actionListener="#{homeController.doSomething}">
                <f:ajax execute="@form"/>
            </h:commandButton>
        </h:form>
    </h:body>
</html>

So far everything goes well untill now. When the session timeout occur and if I click on the Primefaces's button or the ajax enabled JSF's button it does nothing, neither any exception nor the actionListener get called; that is okay; but I am excepting that I would get navigated to the login page.

I can see a POST get fired if I click on the ajax enabled buttons by Firebugging but that is it. If I click on the JSF's button (non-ajax) I am navigating to the login page but not if I click on the other two.

Does JAAS works with AJAX POST? Is it an issue of my code? Am I missing something?

My configuration is:

  • Server - JBoss AS 7.1
  • Mojara - 2.1.7
  • Primefaces - 3.4.2
Tapas Bose
  • 28,796
  • 74
  • 215
  • 331
  • 1
    Install OmniFaces and this problem will completely disappear like magic without any additional configuration. – BalusC Jan 03 '14 at 08:29
  • @BalusC yes I did. The `FullAjaxExceptionHandlerFactory` worked like a charm. Could you explain me the behaviour, why it doesn't work with this `ExceptionHandlerFactory`? – Tapas Bose Jan 03 '14 at 09:08
  • You didn't need additional configuration for this specific case. Explanation is in answer of this duplicate question: http://stackoverflow.com/questions/12504131/viewexpiredexception-not-thrown-on-ajax-request-if-jsf-page-is-protected-by-j-se/ – BalusC Jan 03 '14 at 09:13
  • @BalusC could you please explain `However, as it's an ajax request and there's no render information (the whole POST request is basically discarded during the security check forward), only the view state will be returned.` annotated from the post you have given. It is not very much clear to me. – Tapas Bose Jan 03 '14 at 10:11
  • @BalusC the only point that is unclear is if the the `FacesServlet` generates the view of the login page and since this view is unprotected how come this view get discarded by the security! – Tapas Bose Jan 03 '14 at 11:17

0 Answers0