ZK + Spring Security Login form–Part 5

Connect with database and check user exists or not.

In this post, let us how we can secure ZK Application using custom spring security login form designed in ZK Framework.

So what we are going to do ?

1. We will login page and spring authentication to access the secured pages.
2. After successful authentication, we will re direct to user lists page and from which we can add/edit/delete users.
3. We will also have logout method in the listing page. On Click , it will redirect to login page again.

 

Step 1:
Follow this post and complete all the steps. At the end of the exercise, we will be able add users/edit/delete users. Now we will secure this application using ZK Login page.

Step 2:
First let us update the POM.xml as follows

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>zkloginexample5</groupId>
<artifactId>zkloginexample5</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<zk.version>6.5.1</zk.version>
<commons-io>1.3.1</commons-io>
<maven.build.timestamp.format>yyyy-MM-dd</maven.build.timestamp.format>
<packname>-${project.version}-FL-${maven.build.timestamp}</packname>
</properties>
<packaging>war</packaging>
<name>The zkloginexample5 Project</name>
<description>The zkloginexample5 Project</description>
<licenses>
<license>
<name>GNU LESSER GENERAL PUBLIC LICENSE, Version 3</name>
<url>http://www.gnu.org/licenses/lgpl.html</url>
<distribution>repo</distribution>
</license>
</licenses>
<repositories>
<repository>
<id>ZK CE</id>
<name>ZK CE Repository</name>
<url>http://mavensync.zkoss.org/maven2</url>
</repository>
<repository>
<id>ZK EVAL</id>
<name>ZK Evaluation Repository</name>
<url>http://mavensync.zkoss.org/eval</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>zkmaven</id>
<name>ZK Maven Plugin Repository</name>
<url>http://mavensync.zkoss.org/maven2/</url>
</pluginRepository>
</pluginRepositories>
<dependencies>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zkbind</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zul</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zkplus</artifactId>
<version>${zk.version}</version>
</dependency>
<dependency>
<groupId>org.zkoss.zk</groupId>
<artifactId>zhtml</artifactId>
<version>${zk.version}</version>
</dependency>

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io}</version>
</dependency>

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.9.Final</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>3.0.5.RELEASE</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>

<!-- AOP dependency -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>

<!-- Persistence Management -->
<dependency> <!-- Apache BasicDataSource -->
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.2.2</version>
</dependency>

<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.22</version>
</dependency>

<!-- ZK 5 breeze theme <dependency> <groupId>org.zkoss.theme</groupId>
<artifactId>breeze</artifactId> <version>${zk.version}</version> <optional>true</optional>
</dependency> -->
</dependencies>
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<!-- Run with Jetty -->
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<version>6.1.10</version>
<configuration>
<scanIntervalSeconds>5</scanIntervalSeconds>
<stopKey>foo</stopKey>
<stopPort>9999</stopPort>
</configuration>
<executions>
<execution>
<id>start-jetty</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<scanIntervalSeconds>0</scanIntervalSeconds>
<daemon>true</daemon>
</configuration>
</execution>
<execution>
<id>stop-jetty</id>
<phase>post-integration-test</phase>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Compile java -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<!-- Build war -->
<plugin>
<artifactId>maven-war-plugin</artifactId>
<groupId>org.apache.maven.plugins</groupId>
<version>2.1.1</version>
</plugin>
<!-- Pack zips -->
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>webapp</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>zkloginexample5${packname}</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>assembly/webapp.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>


Step 3:
Next we will create our login.zul. Select the webapp folder, right click, select New –>Other->zul file and enter the zul file name as login.zul
image

image
Here is the login.zul code


<?page id="loginPage" title="Digital medical sheet - Login page" onLoad="win.doOverlapped();"?>
<window id="win" title="LOGIN" border="normal" width="300px"
position="center">

<!-- this form-login-page form is also used as the
form-error-page to ask for a login again. -->
<html style="color:red" if="${not empty param.login_error}">


<![CDATA[ Your login attempt was not successful, try
again.<br/><br/> Reason:
${SPRING_SECURITY_LAST_EXCEPTION.message} ]]>


</html>

<groupbox>
<caption>Login</caption>
<h:form id="f" name="f" action="j_spring_security_check"
method="POST" xmlns:h="http://www.w3.org/1999/xhtml">
<grid>
<columns sizable="false">
<column width="50%" />
<column width="50%" />
</columns>
<rows>
<row>
<label value="User:" />
<textbox id="u" name="j_username" />
</row>
<row>
<label value="Password:" />
<textbox id="p" type="password"
name="j_password" />
</row>
<row spans="2">
<div align="center">
<h:input type="submit" value="login" />
<h:input type="reset" value="Reset" />
</div>
</row>
</rows>
</grid>
</h:form>
</groupbox>
</window>


Step 4:
Next we will update web.xml file. You can copy the content here.

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

<description><![CDATA[My ZK Application]]></description>
<display-name>zkloginexample5</display-name>

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml
/WEB-INF/spring-security.xml
</param-value>
</context-param>
<!-- Loads the Spring web application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>


<!-- A servlet filter capturing every user requests and sending them to
the configured security filters to make sure access is authorized. -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

<!-- Spring filter -->
<filter>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>OpenEntityManagerInViewFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- //// -->

<!-- //// -->
<!-- ZK -->
<listener>
<description>ZK listener for session cleanup</description>
<listener-class>org.zkoss.zk.ui.http.HttpSessionListener</listener-class>
</listener>
<servlet>
<description>ZK loader for ZUML pages</description>
<servlet-name>zkLoader</servlet-name>
<servlet-class>org.zkoss.zk.ui.http.DHtmlLayoutServlet</servlet-class>

<!-- Must. Specifies URI of the update engine (DHtmlUpdateServlet). It
must be the same as <url-pattern> for the update engine. -->
<init-param>
<param-name>update-uri</param-name>
<param-value>/zkau</param-value>
</init-param>
<!-- Optional. Specifies whether to compress the output of the ZK loader.
It speeds up the transmission over slow Internet. However, if you configure
a filter to post-processing the output, you might have to disable it. Default:
true <init-param> <param-name>compress</param-name> <param-value>true</param-value>
</init-param> -->
<!-- [Optional] Specifies the default log level: OFF, ERROR, WARNING, INFO,
DEBUG and FINER. If not specified, the system default is used. <init-param>
<param-name>log-level</param-name> <param-value>OFF</param-value> </init-param> -->
<load-on-startup>1</load-on-startup><!-- Must -->
</servlet>
<servlet-mapping>
<servlet-name>zkLoader</servlet-name>
<url-pattern>*.zul</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>zkLoader</servlet-name>
<url-pattern>*.zhtml</url-pattern>
</servlet-mapping>
<!-- [Optional] Uncomment it if you want to use richlets. <servlet-mapping>
<servlet-name>zkLoader</servlet-name> <url-pattern>/zk/*</url-pattern> </servlet-mapping> -->
<servlet>
<description>The asynchronous update engine for ZK</description>
<servlet-name>auEngine</servlet-name>
<servlet-class>org.zkoss.zk.au.http.DHtmlUpdateServlet</servlet-class>

<!-- [Optional] Specifies whether to compress the output of the ZK loader.
It speeds up the transmission over slow Internet. However, if your server
will do the compression, you might have to disable it. Default: true <init-param>
<param-name>compress</param-name> <param-value>true</param-value> </init-param> -->
<!-- [Optional] Specifies the AU extension for particular prefix. <init-param>
<param-name>extension0</param-name> <param-value>/upload=com.my.MyUploader</param-value>
</init-param> -->
</servlet>
<servlet-mapping>
<servlet-name>auEngine</servlet-name>
<url-pattern>/zkau/*</url-pattern>
</servlet-mapping>

<!-- [Optional] Uncomment if you want to use the ZK filter to post process
the HTML output generated by other technology, such as JSP and velocity.
<filter> <filter-name>zkFilter</filter-name> <filter-class>org.zkoss.zk.ui.http.DHtmlLayoutFilter</filter-class>
<init-param> <param-name>extension</param-name> <param-value>html</param-value>
</init-param> <init-param> <param-name>compress</param-name> <param-value>true</param-value>
</init-param> </filter> <filter-mapping> <filter-name>zkFilter</filter-name>
<url-pattern>your URI pattern</url-pattern> </filter-mapping> -->
<!-- //// -->

<!-- ///////////// -->
<!-- DSP (optional) Uncomment it if you want to use DSP However, it is turned
on since zksandbox uses DSP to generate CSS. <servlet> <servlet-name>dspLoader</servlet-name>
<servlet-class>org.zkoss.web.servlet.dsp.InterpreterServlet</servlet-class>
<init-param> <param-name>class-resource</param-name> <param-value>true</param-value>
</init-param> </servlet> <servlet-mapping> <servlet-name>dspLoader</servlet-name>
<url-pattern>*.dsp</url-pattern> </servlet-mapping> -->

<!-- /////////// -->
<!-- [Optional] Session timeout -->
<session-config>
<session-timeout>60</session-timeout>
</session-config>

<!-- [Optional] MIME mapping -->
<mime-mapping>
<extension>doc</extension>
<mime-type>application/vnd.ms-word</mime-type>
</mime-mapping>
<mime-mapping>
<extension>gif</extension>
<mime-type>image/gif</mime-type>
</mime-mapping>
<mime-mapping>
<extension>htm</extension>
<mime-type>text/html</mime-type>
</mime-mapping>
<mime-mapping>
<extension>html</extension>
<mime-type>text/html</mime-type>
</mime-mapping>
<mime-mapping>
<extension>jpeg</extension>
<mime-type>image/jpeg</mime-type>
</mime-mapping>
<mime-mapping>
<extension>jpg</extension>
<mime-type>image/jpeg</mime-type>
</mime-mapping>
<mime-mapping>
<extension>js</extension>
<mime-type>text/javascript</mime-type>
</mime-mapping>
<mime-mapping>
<extension>pdf</extension>
<mime-type>application/pdf</mime-type>
</mime-mapping>
<mime-mapping>
<extension>png</extension>
<mime-type>image/png</mime-type>
</mime-mapping>
<mime-mapping>
<extension>txt</extension>
<mime-type>text/plain</mime-type>
</mime-mapping>
<mime-mapping>
<extension>xls</extension>
<mime-type>application/vnd.ms-excel</mime-type>
</mime-mapping>
<mime-mapping>
<extension>xml</extension>
<mime-type>text/xml</mime-type>
</mime-mapping>
<mime-mapping>
<extension>zhtml</extension>
<mime-type>text/html</mime-type>
</mime-mapping>
<mime-mapping>
<extension>zul</extension>
<mime-type>text/html</mime-type>
</mime-mapping>

<welcome-file-list>
<welcome-file>UserList.zul</welcome-file>
<welcome-file>index.zhtml</welcome-file>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
</welcome-file-list>
</web-app>

Step 5:
Next we will create spring-security.xml in the webapp\web-INF folder. Select the webapp folder, right click, Select New->Other->xml file and enter the file name as “spring-security.xml”

image

image
You can copy the code from here.


<!-- Spring namespace-based configuration -->

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.0.xsd">

<!-- ====================================================== -->
<!-- For catching the @Secured annotation methods -->
<!-- Tells the Spring Security engine that we will use Spring Security's -->
<!-- pre and post invocation Java annotations (@PreFilter, @PreAuthorize, -->
<!-- @PostFilter, -->
<!-- @PostAuthorize) to secure service layer methods.. -->
<!-- Look in GFCBaseCtrl.java onEvent() method. -->
<!-- ====================================================== -->

<!-- Enable the @Secured annotation to secure service layer methods -->
<global-method-security secured-annotations="enabled" />

<http auto-config="true">

<!-- ====================================================== -->
<!-- If we have our own LoginPage. So we must -->
<!-- tell Spring the name and the place. -->
<!-- In our case we take the same page -->
<!-- for a error message by a failure. -->
<!-- Further the page after a successfully login. -->
<!-- ====================================================== -->
<form-login login-page="/login.zul"
authentication-failure-url="/login.zul?login_error=1"
default-target-url="/UserList.zul" always-use-default-target="true" />
<intercept-url pattern="/login.zul" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<intercept-url pattern="/*.zul" access="IS_AUTHENTICATED_REMEMBERED" />
</http>

<authentication-manager>
<authentication-provider user-service-ref="myUserDetailsService">

</authentication-provider>
</authentication-manager>

<beans:bean id="myUserDetailsService" class="crudexample.service.MyUserDetailsService" />


</beans:beans>



Step 6:
Next we will update applicationContext.xml file. You can copy the content here.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">


<!-- The LocalEntityManagerFactoryBean creates an EntityManagerFactory suitable for environments which solely use JPA for data access.
The factory bean will use the JPA PersistenceProvider autodetection mechanism (according to JPA's Java SE bootstrapping) and,
in most cases, requires only the persistence unit name to be specified:
-->

<bean id="entityManagerFactory"
class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<property name="persistenceUnitName" value="ZKExamples" />
</bean>


<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<!-- tell spring to use annotation based congfigurations -->
<!-- It allow us to use @Autowire, @Required and @Qualifier annotations. -->

<context:annotation-config />

<!-- tell spring where to find the beans -->
<!-- tells Spring to scan the code for injectable beans under the package (and all its subpackages) specified. -->
<!-- It allow @Component, @Service, @Controller, etc.. annotations. -->
<context:component-scan base-package="crudexample" />

<tx:annotation-driven transaction-manager="transactionManager" />

<!-- This will ensure that hibernate or jpa exceptions are automatically
translated into Spring's generic DataAccessException hierarchy for those
classes annotated with Repository -->

<bean
class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />

<bean id="CRUDService" class="crudexample.service.CRUDServiceImpl" />

</beans>

Step 7:
Next we will need to update our dao and service layer by adding one more method to execute namedquery.
CRUDDao.java


package crudexample.dao;

import java.util.List;

public interface CRUDDao {

<T> List<T> getAll(Class<T> klass);

<T> T save(T t);

<T> T GetUniqueEntityByNamedQuery(String query, Object... params);

<T> void delete(T t);
}
CRUDDaoImpl.java

package crudexample.dao;

import java.util.List;
import java.util.Set;

import javax.persistence.EntityManager;
import javax.persistence.Parameter;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;

import org.springframework.stereotype.Repository;

@Repository
public class CRUDDaoImpl implements CRUDDao {

@PersistenceContext(type = PersistenceContextType.EXTENDED)
private EntityManager em;

public EntityManager getEm() {
return em;
}

public void setEm(EntityManager em) {
this.em = em;
}

@SuppressWarnings("unchecked")
public <T> List<T> getAll(Class<T> klass) {
return em.createQuery("Select t from " + klass.getSimpleName() + " t")
.getResultList();
}

public <T> T save(T t) {
T newRecord = null;
newRecord = em.merge(t);
return newRecord;
}

public <T> void delete(T t) {
em.remove(em.merge(t));
em.flush();
}

@SuppressWarnings("unchecked")
public <T> T GetUniqueEntityByNamedQuery(String query, Object... params) {

System.out.println("results is ");
Query q = this.em.createNamedQuery(query);
int i = 1;

for (Object o : params) {
q.setParameter(i, o);
}

List<T> results = q.getResultList();
System.out.println("results is "+ results.size());
T foundentity = null;
if (!results.isEmpty()) {
// ignores multiple results
foundentity = results.get(0);
}
return foundentity;
}
}


CRUDService.java

package crudexample.service;

import java.util.List;

public interface CRUDService {
<T> List<T> getAll(Class<T> klass);

<T> T save(T t);

<T> T GetUniqueEntityByNamedQuery(String query, Object... params);

<T> void delete(T t);


}


CRUDServiceImpl.java

package crudexample.service;


import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import crudexample.dao.CRUDDao;


@Service
public class CRUDServiceImpl implements CRUDService {


@Autowired
private CRUDDao CRUDDao;

@Transactional(readOnly = true)
public <T> List<T> getAll(Class<T> klass) {
return CRUDDao.getAll(klass);
}


@Transactional
public <T> T save(T t) {
T newRecord = null;
newRecord = CRUDDao.save(t);
return newRecord;
}

@Transactional
public <T> void delete(T t) {
CRUDDao.delete(t);
}

@Transactional
public <T> T GetUniqueEntityByNamedQuery(String query, Object... params) {
return CRUDDao.GetUniqueEntityByNamedQuery(query, params);
}
}
Step 8:
Next we will create our custom authentication by extending spring UserDetailsService interface. Select the “service” package, right click, select new->Other->Class and enter the class name as “MyUserDetailsService”.

package crudexample.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import crudexample.domain.Appusers;

public class MyUserDetailsService implements UserDetailsService {

@Autowired
private CRUDService CRUDService;

/*
* You just have to make sure that the user-by-username-query returns three
* fields. 1) the userName 2) the password 3) boolean for is the user
* active. If you don't have an active field, make your query always return
* true for that third field.
*/
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {

// Declare a null Spring User
UserDetails user = null;

try {

// Search database for a user that matches the specified username
// You can provide a custom DAO to access your persistence layer
// Or use JDBC to access your database
// DbUser is our custom domain user. This is not the same as
// Spring's User

Appusers dbUser = CRUDService.GetUniqueEntityByNamedQuery(
"Appusers.findUserByUserID", username);

// Populate the Spring User object with details from the dbUser
// Here we just pass the username, password, and access level
// getAuthorities() will translate the access level to the correct
// role type

user = new User(dbUser.getUserID(), dbUser.getPassword()
.toLowerCase(), true, true, true, true,
getAuthorities());

} catch (Exception e) {
throw new UsernameNotFoundException("Error in retrieving user");
}

// Return user to Spring for processing.
// Take note we're not the one evaluating whether this user is
// authenticated or valid
// We just merely retrieve a user that matches the specified username

return user;
}

/**
* Retrieves the correct ROLE type depending on the access level, where
* access level is an Integer. Basically, this interprets the access value
* whether it's for a regular user or admin.
*
* @param access
* an integer value representing the access of the user
* @return collection of granted authorities
*/
public Collection<GrantedAuthority> getAuthorities() {
// Create a list of grants for this user
List<GrantedAuthority> authList = new ArrayList<GrantedAuthority>(2);

// All users are granted with ROLE_USER access
// Therefore this user gets a ROLE_USER by default
authList.add(new GrantedAuthorityImpl("ROLE_USER"));
// User has admin access
authList.add(new GrantedAuthorityImpl("ROLE_ADMIN"));

// Return list of granted authorities
return authList;
}
}

Step 9:
Next we will add logout option in the userlist.zul file as follows. Just add one more button next add new button

	<div style="float:right">
<button label="Add New" mold="trendy" id="btnNew"
sclass="mybutton button blue small" />
<button label="Logout" mold="trendy" id="btnlogout"
sclass="mybutton button blue small" />

</div>


And also, add the following code in the controller.


	public void onClick$btnlogout(Event event)
{
Executions.sendRedirect("/j_spring_security_logout");
}

Now you select the Project and Run using tomcat server.
You can download the source
here