Now, after we’ve addressed basic log-in with simple file realm, I want to move on by exchanging the authentication method. Remember, this tutorial is about web development with JavaServer Faces. All I showed for container based security so far, is technology entirely independent from JSF. Same applies to simple form log-in. But, it’s possible to embed this into some JSF techniques. And, further on, using programmatic log-in, this is done by the use of JSF.

For the form based log-in, we slightly have to change our web.xml. Beside changing the authentication method, we have to declare two pages, one for the log-in and one failure page (which might be the same).

Thus, replace

<login-config>
       <auth-method>BASIC</auth-method>
       <realm-name>file</realm-name>
</login-config>

by

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

And this is a short login page:

<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html">
       <h:head>
               <title>Login</title>
       </h:head>
       <h:body>
               <form   method="POST" action="j_security_check">
                       Username: <input type="text" name="j_username" />
                       Password: <input type="password" name="j_password" />
                       <br />
                       <input type="submit" value="Login" />
                       <input type="reset" value="Reset" />
               </form>
       </h:body>
</html>

Since this mainly is a JSF tutorial, I used NetBeans’ New, JSF Page to create a stub. But the heart of this page is pure HTML, a form with method POST and action “j_security_check”. This name is fixed, as well as the names for the user and password fields. If you like, you may insert this form into a fully fledged JSF page. Remember to use this standard HTML for, which you may place beside a <h:form …/> which you may use for other purpose. Or you may embed this login form into a JSF component to make it more re-usable.

And here an example for the error page. You may use any page. Here, I used some simple JSF without any backing bean.

<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html">
       <h:head>
               <title>Login Error</title>
       </h:head>
       <h:body>
               <div>
                       <h:outputText value="Sorry, you could not be identified."/>
               </div>
               <div>
                       <h:button outcome="/login.xhtml" value="Try again."/>
               </div>
       </h:body>
</html>

Start your app, and it should use form authentication. Nothing more to talk about.

From my point of view, programmatic login is much more interesting than this fixed form. To do this, we’ll keep the web.xml as defined above. But, instead of using this fixed HTML form, we use a JSF form with the login moved into a backing bean.

Here is the modified form:

<?xml version='1.0' encoding='UTF-8' ?>
<!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://xmlns.jcp.org/jsf/html">
       <h:head>
               <title>Login</title>
       </h:head>
       <h:body>
               <h:form>
                       <div>
                               <h:outputLabel for="userName" value="User"/>
                               <h:inputText id="userName" value="#{login.userName}" 
                                                         required="true" 
                                                         requiredMessage="Please enter username"/>
                       </div>
                       <div>
                               <h:outputLabel for="password" value="Password"/>
                               <h:inputSecret id="password" value="#{login.password}" 
                                                             required="true" 
                                                             requiredMessage="Please enter password"/>
                       </div>
                       <div>
                               <h:commandButton action="#{login.login}" value="Login"/>
                       </div>
               </h:form>
       </h:body>
</html>

This is a fully fledged JSF page. And it’s up to you, to design it as you like. User name and password fields are mandatory now. This is guaranteed by the use of the required property. They are stored into two properties of the backing bean. And, if the user clicks onto the login button, the login action is performed.

public String login() {
       FacesContext context = FacesContext.getCurrentInstance();
       HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();

       try {
              request.login(_userName, _password);
       } catch (ServletException e) {
              context.addMessage(null, new FacesMessage("Login failed."));
              return "/loginError";
       }
       return "/index";
}

First, you have to obtain the HttpServletRequest and then delegate the login by calling it’s login method. Quite simple, isn’t it? If login fails, a ServletException exception is thrown. I simply created a FacesMessage, which will be displayed in the user’s browser. Instead of returning “/loginError”, it’s possible to return “/login”. Doing so, the login form will be re-displayed with the failure message (don’t forget to add a message tag to this page). Although this method does not care about the <form-error-page> tag of web.xml, you can’t omit this tag. It’s still required, but it’s content doesn’t care.

Next, I’m going to show you, how to exchange the password store. At first, we’ll move to jdbcRealm. This allows you to store your user and password information in a database. Stay tuned!

 

Go to web development tutorial table of content.