A very simple login example with JSF
Following the very simple example line, as in the “login example with Rails“, now we’ll see a very simple login example with Java Server Faces.
I’m writing this sequence of short howto posts because in the forums I read one of the recurrent question from the beginners is “how to implement a login with X”, so, let’s go to the JSF login example.
Of course there are many ways to implement a login in a JSF aplication, you can use JAAS, you can use a Servlet Filter, but this one I think is one of the best approaches, of course, in a real application, I usually combine it with some AOP and annotations, but AOP and annotations are out of the scope of this tutorial …
First, write a web.xml for your application, with the faces servlet in it …
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <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> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.jsf</url-pattern> </servlet-mapping> <error-page> <exception-type>java.lang.SecurityException</exception-type> <location>/login.jsf</location> </error-page> </web-app>
In this web.xml we are using the servlets 2.5 specification, and I’m using JSF 1.2, for this example you can use other versions without problem.
The servlet container is configured to show a login page if at any time the application throws a java.lang.SecurityException, this is a important point for the example.
And now a backing bean for the application, here is where we’ll validate the user’s login, in this example there is no need for database access, but in a real application you’ll search this data in your user repository (database, ldap, …)
package br.com.urubatan.jsfjpasec; public class Login { private boolean loginOk; private String userName; private String password; public boolean isLoginOk() { return loginOk; } 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 validateLogin(){ if(userName!=null && password!=null && !userName.equalsIgnoreCase(password)){ loginOk = true; return "secpage"; }else return "login"; } }
It is a very simple backing bean, with only 3 properties:
name and password for the user, and a property telling the application that a user has already logged in.
probably this last property will be replaced by a list of groups filled by the validateLogin method …
Now a bean with some static data for the example:
package br.com.urubatan.jsfjpasec; import java.util.List; import java.util.ArrayList; public class SomeData { private List<String> data = new ArrayList<String>(); private List<String> securedData = new ArrayList<String>(); private boolean loginOk; public SomeData() { for(int i=0;i<10;i++){ data.add("Simple data " + i); securedData.add("Secure data " + i); } } public void setLoginOk(boolean loginOk) { this.loginOk = loginOk; } public List<String> getSecuredData() { if(!loginOk) throw new SecurityException(); return securedData; } public List<String> getData() { return data; } }
This one has only the getters for two properties, and in the secureData property, if there is no logged in user, the application throws a java.lang.SecurityException, this will redirect the user to the login page.
Now some XML tricks in the faces-config.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <?xml version='1.0' encoding='UTF-8'?> <faces-config xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd" version="1.2"> <managed-bean> <managed-bean-name>login</managed-bean-name> <managed-bean-class>br.com.urubatan.jsfjpasec.Login</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> <managed-bean> <managed-bean-name>mdata</managed-bean-name> <managed-bean-class>br.com.urubatan.jsfjpasec.SomeData</managed-bean-class> <managed-bean-scope>request</managed-bean-scope> <managed-property> <property-name>loginOk</property-name> <property-class>java.lang.Boolean</property-class> <value>#{login.loginOk}</value> </managed-property> </managed-bean> <navigation-rule> <from-view-id>/login.jsp</from-view-id> <navigation-case> <from-outcome>login</from-outcome> <to-view-id>/login.jsp</to-view-id> <redirect/> </navigation-case> <navigation-case> <from-outcome>secpage</from-outcome> <to-view-id>/secureView.jsp</to-view-id> <redirect/> </navigation-case> </navigation-rule> </faces-config> |
In this file we have two navigation cases, if “login” is returned from a backing bean, it shows the login page, if “secpage” is returned, the secureView.jsp page is shown …
The first lines are used to declare the backing beans, pay attention to the line 15, where we are reading the property “loginOk” from the login bean.
The login bean is session scoped, and the mdata is request scoped.
With this written we have all the needed logic for this application, the only missing part is the “view”, or the JSP files …
So, let’s write them …
login.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <html> <head><title>System Login</title></head> <body> <f:view> <h:form> <h:panelGrid columns="2"> <h:outputLabel value="User Name" for="un"/> <h:inputText id="un" value="#{login.userName}"/> <h:outputLabel value="Password" for="pw"/> <h:inputText id="pw" value="#{login.password}"/> </h:panelGrid> <h:commandButton value="Login" action="#{login.validateLogin}"/> </h:form> </f:view> </body> </html>
This is only a simple JSF page with two fields and a commandButton …
dataView.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <html> <head><title>Unsecured Data Page</title></head> <body> <f:view> <h:dataTable value="#{mdata.data}" var="v"> <h:column> <f:facet name="header"> <h:outputText value="Data List"/> </f:facet> <h:outputText value="#{v}"/> </h:column> </h:dataTable> <h:panelGrid columns="3"> <h:outputLink value="dataView.jsf"> <h:outputText value="Data that every one can access"/> </h:outputLink> <h:outputLink value="secureView.jsf"> <h:outputText value="Data that you can view after login"/> </h:outputLink> <h:outputLink value="login.jsf"> <h:outputText value="Login"/> </h:outputLink> </h:panelGrid> </f:view> </body> </html>
This is simple page with a dataTable rendering the “data” property from “mdata” bean and two links.
secureView.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %> <%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %> <html> <head><title>Secured Data Page</title></head> <body> <f:view> <h:dataTable value="#{mdata.securedData}" var="v"> <h:column> <f:facet name="header"> <h:outputText value="Data List"/> </f:facet> <h:outputText value="#{v}"/> </h:column> </h:dataTable> <h:panelGrid columns="3"> <h:outputLink value="dataView.jsf"> <h:outputText value="Data that every one can access"/> </h:outputLink> <h:outputLink value="secureView.jsf"> <h:outputText value="Data that you can view after login"/> </h:outputLink> <h:outputLink value="login.jsf"> <h:outputText value="Login"/> </h:outputLink> </h:panelGrid> </f:view> </body> </html>
And this is almost a copy from the previous page, but now reading the “secureData” property from “mdata” bean.
And just to avoid the “404″ error when running the application, an “index.jsp” with a link to “dataView.jsf”
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head><title>Entry Page</title></head> <body>Entry Page, this could redirect to the JSF Index, but for now, click here: <a href="dataView.jsf">JSF Index</a> </body> </html>
That is all folks!
to run this application you need the following jar files: jstl.jar, jsf-api.jar e jsf-impl.jar
They can be found in the JSF-RI distribution, and are already present in containers with JSF support.
And now, some questions:
- How would you improve this example?
- Do you see any problem with this approach?
- Are you already using JSF?
If you enjoyed this post, make sure you subscribe to my RSS feed!





[…] Comentários Duda on Teste de QIA very simple login example with JSF | Urubatan’s Weblog on Implementando Login com JSF (exemplo simples)alexandre on DAO Generico - um exemplo a […]
“How would you improve this example?”
Use Seam?
Peace
-stephan
–
Stephan Schmidt :: stephan@reposita.org
Reposita Open Source - Monitor your software development
http://www.reposita.org
Blog at http://stephan.reposita.org - No signal. No noise.
Stephan, Seam is a very good framework, but the idea of this post was to teach how the things work behind the scenes
Too complicated. I can write the same stuff in several code in raw PHP or even less with SolarPHP or Zend or Symfony framework
vnjug, if I want to let this to the container, I can do it with 4 lines of XML too, but this way is more flexible …
And in a real application it will probably be wrapped with a little of annotations and AOP
Urubatan, ah ok.
@vnjug: web.xml is created once and then forgotten. And as Urubatan says, faces-config.xml is usually done with annotations.
Peace
-stephan
[…] here to […]
I have a question, How can I logoff?,
because after login and close the application, I running again and I was still login and could see the “secureData”…
I just have to undeploy and deploy the aplication again??
I use netbeans 6.1 and glassfish.
To logout you just need to create a link that will set the loginOk property of the Login bean to false.