JSF Authentication Example
In our previous example we have learned how to create a sample JSF-HelloWorld application. This article will focus on creating a simple login application using the authentication mechanism and will demonstrate the following.
- How can we navigate from one page to another?
- Sending and retrieving data to and from a managed bean and using the same in another page.
Table Of Contents
1. Introduction
Authentication mechanism allows users to have secure access to the application by validating the username and password. We will have following components in our login application
- LoginBean.java – Managed bean
- index.xhtml – Contains the login form with JSF components
- success.xhtml – If the login is successful, it will show the logged in username
- failure.xhtml – If user credentials are invalid error page will be shown
- faces-config.xml – It’s the JSF configuration file where the success & failure navigation rule will be set
- web.xml – Web application configuration file
But before we create the sample authentication application let’s briefly understand the authentication mechanism in JSF.
The below example shows how to use form-based authentication with a Java Server Faces application. With a form-based application, we can customize the login & error pages that are shown to the client for authentication of the username and password. When a user submits his/her credentials, the server will check whether the user’s credentials are authorized or not. If the user is successfully authenticated, he will be shown the success page or else the error/failure page.
When using the form-based authentication, we specify a page that contains the form for obtaining the username and password. Here is the sample code for this page.
<h:outputLabel value="Username: " /> <h:inputText value="#{loginBean.userName}" /> <h:outputLabel value="Password: " /> <h:inputSecret value="#{loginBean.password}" /> <h:commandButton value="Login" action="#{loginBean.validateUserLogin}" />
The entered credentials will be authenticated by the server and if the user is authorized, he/she will be shown the success page with a welcome message else the failure page with an error message.
This example is based on the JSF method binding approach where the entered credentials will be authenticated against the managed-bean and the user will be shown the expected result based on the navigation rules defined in the JSF configuration.
1.1 JSF Navigation Rule
In simple language, page navigation means the flow of the application from one page to another page. Navigation in JSF defines the set of rules for choosing the next view to be displayed after a specified action is completed.
In JSF, navigation between pages is defined by a set of rules. These rules determine which next page to be displayed depending upon a user clicking a navigation component (such as a button or a hyperlink) or when the navigation is based on the form-based authentication. These navigation rules are defined in JSF configuration file namely faces-config.xml
1.1.1 How to Create Page Navigation Rules
Navigation rule definitions are stored in the JSF configuration file. The general syntax of a JSF navigation rule element in the faces-config.xml
file is shown below:
<navigation-rule> <from-view-id>page-or-pattern</from-view-id> <navigation-case> <from-outcome>outcome</from-outcome> <to-view-id>destination-page</to-view-id> </navigation-case> <navigation-case> ... </navigation-case> </navigation-rule>
A navigation rule can consist of the following elements –
- navigation-rule: A mandatory element for navigation case elements.
- from-view-id: An optional element that contains either a complete page identifier or a page identifier prefix ending with the asterisk (*) character. If we use the wildcard character, the rule applies to all pages that match the wildcard pattern. To make a global rule that applies to all pages, leave this element blank.
- navigation-case: A mandatory element for each case in the navigation rule. Each case defines the different navigation paths from the same page. A navigation rule must have at least one navigation case.
- from-action: An optional element that limits the application of the rule only to outcomes from the specified action method.
- from-outcome: A mandatory element that contains an outcome value that is matched against values specified in the action attribute.
- to-view-id: A mandatory element that contains the complete page identifier of the page to which the navigation is routed when the rule is implemented.
A sample navigation from our example :
<navigation-rule> <from-view-id>/index.xhtml</from-view-id> <navigation-case> <from-action>#{loginBean.validateUserLogin}</from-action> <from-outcome>success</from-outcome> <to-view-id>/success.xhtml</to-view-id> </navigation-case> </navigation-rule>
This code specifies that view index.xhtml
has two outputs – success and failure associated with a particular outcome. Below is the sample managed bean code in which this navigation case is listed:
public String validateUserLogin() { String navResult = ""; System.out.println("Entered Username is= " + userName + ", password is= " + password); if (userName.equalsIgnoreCase("javacodegeeks") && password.equals("access123")) { navResult = "success"; } else { navResult = "failure"; } return navResult; }
1.1.2 Navigation Rule Flow
Here when the Login button is clicked in the index.xhtml
, the request containing the form values is intercepted by the validateUserLogin()
method of the LogicBean class.
Once the credentials are validated, JSF will resolve the success view name in the faces-config.xml
and shows the corresponding result to the user. Similar execution happens in the case of invalid credentials and the user is shown the failure or the error page.
Now, open up the eclipse IDE and let’s start building the application!
2. JSF Authentication Example
2.1 Tools Used
Our preferred environment is Eclipse. We are using Eclipse Kepler SR2, JDK 8 (1.8.0_131) and Tomcat 7 application server. Having said that, we have tested the code against JDK 1.7 and it works well.
2.2 Project Structure
First, let’s review the final project structure, in case you are confused about where you should create the corresponding files or folder later!
2.3 Project Creation
In this section, we will see how to create a Dynmaic Web Java project with Eclipse. In eclipse IDE, go to File -> New -> Dynamic web project
In the New Dynamic Project window fill in the below details and click next
- Enter the project name and project location
- Select Target runtime as Apache Tomcat v7.0 from dropdown
- Select Configuration as JavaServer Faces v.2.2 Project from dropdown (this is required to download the java server faces capabilities in your project)
Leave everything as default in this window as we will be making the required java file at a later stage. Simply click next and we will land up on the web-module window
In the Web Module window, leave the context_root
and content_directory
values as default (however, you can change the context_root
but for this application let’s keep it as a default value). Simply, check Generate web.xml deployment descriptor checkbox and click next
In the JSF Capabilities windows, we will require downloading the dependencies (not available by default) so that our project is configured as a JSF module in Eclipse. Add the JSF capabilities to the web project by clicking on the download icon (encircled in fig. 5) and download the JSF 2.2 mojara implementation
A new pop-up window will open where it will auto lists down the JSF library. Select the JSF 2.2 library and click next (the library name and download destination will be auto populated)
Check the license checkbox and click finish. Eclipse will download the JSF 2.2 library and will display them on the JSF capabilities windows (i.e. fig5)
Now the JSF implementation libraries will be listed down on the capabilities page. Select the checkbox (JSF2.2 (Mojarra 2.2.0)) and leave everything else as default. Click Finish
Eclipse will create the project named JSF Authentication in the workspace and web.xml
will be configured for accepting the JSF requests. It will have the following code:
<?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>JSF Authentication</display-name> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> <welcome-file>default.html</welcome-file> <welcome-file>default.htm</welcome-file> <welcome-file>default.jsp</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>/faces/*</url-pattern> </servlet-mapping> <context-param> <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description> <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> </web-app>
Now let’s start building the application!
3. Application Building
3.1 File Creation
For the demo, we will have an input file containing the form page and the output files on which the result will be displayed based on the authentication result. Right click on project WebContent -> New -> File
Note – In JSF 2.0, it’s recommended to create a JSF page in xhtml format, a file format with .xhtml extension
A pop-up window will open, verify the parent folder location as JSF Authentication/WebContent
and enter the file name (index. xhtml) and click Finish
Repeat the step where we need to create the file for our application (i.e. fig. 9). Again, verify the parent folder location as JSF Authentication/WebContent
and enter the filename (success.xhtml) and click Finish
Again repeat the similar step and enter the file name as – failure.xhtml. Click Finish
3.1.1 Implementation of Index & Output files
Now in order to use the rich UI components, we need to declare the below namespaces at top of the page in the prepared files:
html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html">
Here in the index.xhtml
we will have the form based UI components. The action attribute on the button will show the corresponding result based on the corresponding logic written in the managed-bean. Add the following code to it:
index.xhtml
<!DOCTYPE HTML> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>JSF Authentication</title> <style type="text/css"> .textPlacement { margin: 12px; } </style> </h:head> <h:body> <h2>JSF Authentication Example</h2> <h:form id="loginForm"> <div id="userNameDiv" class="textPlacement"> <h:outputLabel value="Username: " /> <h:inputText value="#{loginBean.userName}" /> </div> <div id="passwordDiv" class="textPlacement"> <h:outputLabel value="Password: " /> <h:inputSecret value="#{loginBean.password}" /> </div> <div id="submitBtn" class="textPlacement"> <h:commandButton value="Login" action="#{loginBean.validateUserLogin}" /> </div> </h:form> </h:body> </html>
In the output page, JSF will display the output based on the authentication result. Add the following code to it:
success.xhtml
<!DOCTYPE HTML> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>JSF Authentication</title> <style type="text/css"> .successText { color: green; margin: 12px; font-weight: bold; } </style> </h:head> <h:body> <div id="result"> Welcome, <span id="userName"><h:outputLabel class="successText" value="#{loginBean.userName}" /></span> </div> </h:body> </html>
failure.xhtml
<!DOCTYPE HTML> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html"> <h:head> <title>JSF Authentication</title> <style type="text/css"> .errorText { color: red; margin: 12px; font-weight: bold; } </style> </h:head> <h:body> <div id="resultErr"> <span id="invalidCre" class="errorText">Invalid Credentials</span> </div> </h:body> </html>
3.2 Java Class Creation
Let’s create the required java files. Right click on src folder New -> Package
A new pop window will open where we will enter the package name, namely com.jsf.authentication
Once the package is created in the application, we will need to create the required managed bean class. Right-click on the newly created package New -> Class
A new pop window will open and enter the file name as LoginBean. The bean class will be created inside the package – com.jsf.authentication
3.2.1 Managed Bean & Implementation of Navigation Rule in faces-config.xml
LoginBean.java
This class has a method validateUserLogin()
which interacts with login action event and does the user authentication based on the entered credentials. In the validateUserLogin()
if the entered credentials matches with the already defined credentials, user will be granted access else the failure page will be displayed
Note – The navigation outcome is specified in the faces-config.xml
for which the code is written below.
package com.jsf.authentication; import javax.faces.bean.ManagedBean; import javax.faces.bean.SessionScoped; @ManagedBean @SessionScoped public class LoginBean { private String userName; private String password; 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; } public String validateUserLogin() { String navResult = ""; System.out.println("Entered Username is= " + userName + ", password is= " + password); if (userName.equalsIgnoreCase("javacodegeeks") && password.equals("access123")) { navResult = "success"; } else { navResult = "failure"; } return navResult; } }
faces-config.xml
In this file, we will specify the navigation rules based on the output of the validateUserLogin()
which is specified in the managed bean i.e. LoginBean.java
<?xml version="1.0" encoding="UTF-8"?> <faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd" version="2.2"> <navigation-rule> <from-view-id>/index.xhtml</from-view-id> <navigation-case> <from-action>#{loginBean.validateUserLogin}</from-action> <from-outcome>success</from-outcome> <to-view-id>/success.xhtml</to-view-id> </navigation-case> <navigation-case> <from-action>#{loginBean.validateUserLogin}</from-action> <from-outcome>failure</from-outcome> <to-view-id>/failure.xhtml</to-view-id> </navigation-case> </navigation-rule> </faces-config>
4. Project Deploy
Once we are ready with all the changes done, let us compile and deploy the application on tomcat7 server. In order to deploy the application on tomcat7, right-click on the project and navigate to Run as -> Run on Server
Tomcat will deploy the application in its webapps folder and shall start its execution to deploy the project so that we can go ahead and test it on the browser
Open your favorite browser and hit the following URL. The output page will be displayed
http://localhost:8082/JSF_Authentication/faces/index.xhtml
Server name (localhost) and port (8082) may vary as per your tomcat configuration
5. Project Demo
When we will hit the application URL, you will see the login page
Enter the credentials javacodegeeks/access123 as username/password and press the login button
If the username and password are correct, the following success message will appear
If the username and password are incorrect, the error message will appear
6. Conclusion
Through this example, we have learned about the authentication mechanism in jsf and how to configure the authentication in eclipse and deploy it using the tomcat7 application server
7. Download the Eclipse Project
This was a JSF authentication example with Eclipse and Tomcat
You can download the full source code of this example here: JSF Authentication
How does this prevent an attacker you from seeing other facelets?
This is JSF Navigation example, not JSF Authentication example.
You also can use a Filter. Check the following:
https://jcodepoint.com/jsf/jsf-autenticacion/