2
votes

I have developed a simple login form to be used in my JSF + PrimeFaces page:

<form action="j_security_check" method="post"> 
    <p:dialog modal="true" header="Login" widgetVar="loginDlg">
        <h:panelGrid columns="3" cellpadding="5">  
            <h:outputLabel for="j_username">Username:</h:outputLabel> 
            <h:inputText id="j_username" required="true" /> 
            <h:message for="j_username" /> 
            <h:outputLabel for="j_password">Password:</h:outputLabel> 
            <h:inputSecret id="j_password" required="true" /> 
            <h:message for="j_password" /> 
            <br /> 
            <h:commandButton value="Login" /> 
        </h:panelGrid>
    </p:dialog>                
</form> 

Tried with an empty password, but the missing password (that is required) is not caught by h:message component. I have also switched to a p:commandButton thinking that the problem could have been in the Ajax behaviour of the button, but the page is not rendered because PrimeFaces complains about the CommandButton not being inside a form element. The exception thrown by the container is:

com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Access denied on empty password for user pippo

To summarize, I have 2 questions:

  1. Why the missing password doesn't produce a message before the form is submitted?
  2. How can I catch a LoginException and display the error message inside the dialog?
1
Try to put there <h:messages />, this should intercept all error messages on whole pagePetr Mensik

1 Answers

6
votes

The j_security_check request is handled by the web container, not by JSF. That explains that the required="true" won't work. It works only when you use JSF <h:form> and programmatic login by HttpServletRequest#login() in the action method associated with the command button.

Best what you can do is to confiure a <form-error-page> in web.xml pointing to the very same URL as the <form-login-page>. You could then check if the request has been forwarded by j_security_check itself, which would mean that a login error has occurred.

<h:panelGroup rendered="#{requestScope['javax.servlet.forward.servlet_path'] == '/j_security_check'}">
    <h:outputText value="Unknown login, please try again" styleClass="error" />
</h:panelGroup>

Use this instead of the <h:message>.

As to why <p:commandButton> complains that there's no form is simply because you didn't use <h:form>.


Unrelated to the concrete problem, that <form> (or <h:form> whenever you would decide to switch to programmatic login) can better be placed in the body of <p:dialog>, not outside. The <p:dialog> can by JS be relocated to end of body which would cause it not to be in a form anymore.