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:

  1. How would you improve this example?
  2. Do you see any problem with this approach?
  3. Are you already using JSF?

Versão em portugues aqui

If you enjoyed this post, make sure you subscribe to my RSS feed!

A very simple login example with Rails

This is just a little step by step on how to create a simple login with Rails, of course you can use a plugin to do it for you, but this way you can understand what the plugin is doing.

Let’s start creating a new Rails application:

$rails applicationName

Then we create a controller with a view for the login:

$script/generate controller login login

The code for the login_controller.rb will be the following:

class LoginController < ApplicationController
def index
render :action => 'login'
end
def login
end
def do_login
username = params[:username]
password = params[:password]
if username.nil? || password.nil? || username==password
redirect_to :action => "login"
flash[:notice] = 'Unknown user or invalid password'
else
session["user_id"] = username
redirect_to :controller => "secure", :action => "index"
end
end
end

Basically the controller has to implement only the do_login method, this is the one that will authenticate the user, in this example it only validates if the user filled the username and password fields, but later you can search the database for it.

The login view will have the following code:

<% form_tag :action => 'do_login' do %>
<table class="loginForm" align="center"><tbody>
<tr>
<td>Login</td>
<td><input name="username" type="text" /></td>
</tr>
<tr>
<td>Password</td>
<td><input name="password" type="password" /></td>
</tr>
<tr>
<td colspan="2"><%= submit_tag "Login" %></td>
</tr>
</tbody></table>
<table><% end %>

It is a simple view, with only two fields and since we do not have a user model I did not used the rails form helpers …

Ok, perfect until now, but how do I use it?

let’s change the application.rb file, the code will be the following:

class ApplicationController < ActionController::Base
# Pick a unique cookie name to distinguish our session data from others'
session :session_key => '_untitled6_session_id'
before_filter :authorize
protected
# Override in controller classes that should require authentication
def secure?
false
end
private
def authorize
if secure? &amp;&amp; session["user_id"].nil?
session["return_to"] = request.request_uri
redirect_to :controller => "login", :action => "login"
return false
end
end
end

The code above adds a before filter to every method of every controller in your application (since all controllers extends ApplicationController), this method will intercept the calls and if the controller is “secure” and the user did not authenticated yet, the user will be redirected to the login page, otherwise the filter will do nothing. To secure a controller you just need to override the “secure?” method and return true.

Now let’s create a simple controller that will need authentication …

$script/generate controller secure index

This line above creates a new controller with only an index action.

Now let’s edit the secure_controller.rb file

class SegureController < ApplicationController
def index
end
protected
def secure?
true
end
end

Overriding the “secure?” method to return true we tell the application that all actions in this controller need authentication.

But if we and only a few actions to need authentication? Than we can use some thing like the code bellow!

protected
def secure?
["secureMethod","anotherSecureMethod"].include?(action_name)
end

This way only the “secureMethod” and the “anotherSecureMethod” will need authentication.

Every thing ready, now we have a login implemented in a rails application …

Try starting the server (ruby script/server from the application’s directory) and access http://localhost:3000/secure and you will see the login screen instead of the index.rhtml contents.

Of course we can improve this example in many ways, for example:

  • in the method do_login we can use the session[”return_to”] to redirect the user to the first requested page.
  • We can create a users/groups structure and implement the authorization using that

And you, how would you improve the example above?

Do you see any problem in this example?

If you enjoyed this post, make sure you subscribe to my RSS feed!