Hibernate based Spring Security Authentication in Web Application.

Scenario:

To perform user authentication in a Web project(I am using Zkoss as a web framework) via Spring by using Hibernate to interact with Database. That is, to remove all JDBC based DB interactions. This is very useful if you want to make your authentication process portable as well as highly flexible.

To start with the new Maven based Web project in eclipse, complete the following steps: 

1. Create a Maven project by following http://paxcel.net/blog/how-to-create-dynamic-web-project-in-eclipse-with-maven-and-zkoss-support-2/

    Note: You can always go for a simple web project.

2. Edit the pom.xml file and add the dependencies for the project as following file.

    Link: Pom.xml

3. Add context and filters tags in web.xml, spring security listener tag in src>main>webapps>WEB-INF>Web.xml as following file. These tags are added to integrate Spring with your web project.

  Located at : /HibernateAuthenication/src/main/webapp/WEB-INF in the Project.

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>

classpath:applicationContext-security.xml

classpath:applicationContext.xml

</param-value>

</context-param>

<!–Spring –>

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

<!– Spring Security –>

<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>

4. Create two new XMLs in resources folder as shown below:

             Files: applicationContext.xml

                      applicationContext-security.xml

5. Open applicationContext.xml and add the content of following file.

    Please focus on the following lines of the file where the transaction-manager for program is defined, later this particular Spring bean will be handled by spring to open, close,  commit or rollback sessions of hibernate.

    <context:component-scanbase-package=“net.paxcel.HibernateAuthentication “/>

    <tx:annotation-driven transaction-manager=“hibernatetransactionManager”>

    </tx:annotation-driven>

    <bean id=“hibernatetransactionManager”class=“org.springframework.orm.hibernate3.HibernateTransactionManager”>

    <propertyname=“sessionFactory”ref=“sessionFactory”/>

    </bean>

6. Open applicationContext-security.xml and add the content of following file in it.

   Most of the file is same as usual applicationContext-security.xml file, but here,instead of writing a pure JDBC query for authentication,we define a bean for authentication  process with a name “userUserDetailsService”.

<sec:authentication-manager>       

<sec:authentication-provideruser-service-ref=“userUserDetailsService”>

</sec:authentication-provider>

</sec:authentication-manager>


Note : The bean userUserDetailsService is defined in step 16 of this document.

7. Add a new properties file with name config.properties in resource folder to setup the database configuration, the content of the file will be as following.

    Note: Your username, password or url can be different from this configuration.

url=jdbc\:mysql\://localhost\:3306/springsecuritytest

dbpassword=password

driver=com.mysql.jdbc.Driver

dbuser=root

dialect=org.hibernate.dialect.MySQLDialect


8. Till now we are done with the following part.

    a. Configuration of pom.xml for project dependency.

    b. Configuration of Web.xml to add spring security.

    c. Configuration of applicationContext.xml to add Hibernate as a data source.

    d. Configuration of applicationContext-security.xml to add security and provide authentication manager to perform hibernate based authentication.

    e. Configuration of config.properties to declare database properties.

9. Edit index.zul(it can index.jsp or index.html in a Dynamic web project) in src>main>webappsas following file.

    Note that the “action” attribute in form(Login form) is referring to “j_spring_security_check”, which is an internal resource of spring to send entered information to spring.

<h:formid=“f”name=“f”action=“j_spring_security_check”method=“POST”xmlns:h=“native”>

10.Create a home.zul(home.jsp/home.html for Dynamic web project) in a folder name “secure” under “src>main>webapp” and edit as follow.

     Note that the logout button on the page refers to “j_spring_security_logout”, which is also a resource of spring authentication service, which is responsible to end the session when user clicks the button.

<buttonlabel=“Logout” href=“../j_spring_security_logout”/>

    Also, you can enable of disable visibility as well as access to some particular part of your page by checking users authority.

Welcome

<zk

if=“${sec:isAllGranted(‘ROLE_ADMIN’)}”>

Your Role is Admin

</zk>

Same type of checks can be applied to jsp pages by including:

<%@ taglib prefix=”sec” uri=”http://www.springframework.org/security/tags” %>

and

<sec:authorize access=”hasRole(‘supervisor’)”>

This content will only be visible to users who have the "supervisor" authority in their list of <tt>GrantedAuthority</tt>s. </sec:authorize>
at the header and body of jsp page.

11. Now create java classes according to the following structure.

12. User.java

      One of the most important parts of program is this class, because here spring executes its internal methods to ensures various checks of user, the class implements UserDetails, which is a class of spring it-self, which will later on hold every information about user and its authorities.

import javax.persistence.*;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.UserDetails;@Entity
@Table(name = “USERS”)
public class User implements UserDetails {
// Original props
@Id
@GeneratedValue
@Column(name=”id_user”)
private Long userId;@Column(name = “username”)
private String username;@Column(name = “password”)
private String password;@Column(name = “enabled”)
private Boolean enabled;// bi-directional one-to-many association to Authority@OneToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER)
@JoinTable(name = “user_authorities”, joinColumns = { @JoinColumn(name = “id_user”)},
inverseJoinColumns={@JoinColumn(name=”id_authority”)})
private Set<Authority> authoritySet;// Getters & Setters for original props
// Please include getters and setters for the variables defined above.
// Spring Security props for internal checks of UserDetails

private transient Collection<GrantedAuthority> authorities;
// UserDetails methods

@Transient
public Collection<GrantedAuthority> getAuthorities() {
return authorities;
}

@Transient
public boolean isAccountNonExpired() {
return true;
}

@Transient
public boolean isAccountNonLocked() {
return true;
}

@Transient
public boolean isCredentialsNonExpired() {
return true;
}

@Transient
public boolean isEnabled() {
return getEnabled();
}

@Transient
public void setUserAuthorities(List<String> authorities) {
List<GrantedAuthority> listOfAuthorities = new ArrayList<GrantedAuthority>();
for (String role : authorities) {
listOfAuthorities.add(new GrantedAuthorityImpl(role));
}
this.authorities = (Collection<GrantedAuthority>) listOfAuthorities;
}


13. Authority.java

import javax.persistence.*;@Entity
@Table(name=”AUTHORITIES”)public class Authority{@Id
@GeneratedValue
@Column(name=”id_authority”)
private Long authorityId;@Column(name=”authority”)
private String authority;// Getters & Setters for original props
}


14. UserDao.java

public interface UserDao
{
User getUserByUserName(String userName);
}


15. UserDaoImpl.java

    This is core class which fetches the data from the database. Note that the class contains a Resource names “sessionFactory”, whenever any method which contains a hibernate query is called, it needs hibernate session to execute the query and that session is provided by sessionFactory (which is a bean provided by spring to handle the hibernate session).

@Repository(“userDao”)
public class UserDaoImpl implements UserDao {@Resource
private SessionFactory sessionFactory;public Session getCurrentSession() {
return this.sessionFactory.getCurrentSession();
}@Override
@Transactional(“hibernatetransactionManager”)
public User getUserByUserName(String userName) {
Query queryResult;
queryResult =getCurrentSession().createQuery(“from User where username=:userName”);
queryResult.setParameter(“userName”, new String(userName));
return (User) queryResult.list().get(0);
}
}

16. UserUserDetailsService.java

     This is the final class which puts everything together. Please note that the password is never checked by the code, spring only gets the user-beans according to its name and that automatically checks if the password is matching or not.

@Repository(“userUserDetailsService”)
public class UserUserDetailsService implements UserDetailsService {

@Resource
private UserDao userDao;

public UserUserDetailsService()
{
}

public UserUserDetailsService(UserDao userDao) {
this.userDao = userDao;
}

public UserDetails loadUserByUsername(String userName)
throws UsernameNotFoundException, DataAccessException {
User user;
List<String> authorityList=new ArrayList<String>();
String authority;
try {
user = userDao.getUserByUserName(userName);
}
catch (Exception e) {
throw new UsernameNotFoundException(
“getUserByUserName returned null.”);
}
Set<Authority> authoritySet=user.getAuthoritySet();
Iterator<Authority> authoritySetIterator=authoritySet.iterator();
while(authoritySetIterator.hasNext())
{
authority=authoritySetIterator.next().getAuthority();
authorityList.add(authority);
}
user.setUserAuthorities(authorityList);
return (UserDetails) user;
}
}


17. Run the following SQL Script to create a basic table in your MySQL database.

 

create database if not exists `springsecuritytest`;

USE `springsecuritytest`;

/*Table structure for table `authorities` */
CREATE TABLE `authorities` (
`id_authority` bigint(20) NOT NULL AUTO_INCREMENT,
`authority` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id_authority`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;

/*Data for the table `authorities` */
insert into `authorities` values
(1,’ROLE_ADMIN’),
(2,’ROLE_MEMBER’);

/*Table structure for table `users` */
CREATE TABLE `users` (
`id_user` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`enabled` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id_user`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1;

/*Data for the table `users` */
insert into `users` values
(1,’root’,’root’,1),
(2,’user’,’user’,1);
SET FOREIGN_KEY_CHECKS=1;

/*Table structure for table `user_authorities` */
CREATE TABLE `user_authorities` (
`id_user` bigint(20) NOT NULL,
`id_authority` bigint(20) NOT NULL,
PRIMARY KEY (`id_user`,`id_authority`),
UNIQUE KEY `id_authority` (`id_authority`),
KEY `FKCE1004AD633BFFF9` (`id_authority`),
KEY `FKCE1004AD7F8F8A43` (`id_user`),
CONSTRAINT `FKCE1004AD7F8F8A43` FOREIGN KEY (`id_user`) REFERENCES `users` (`id_user`),
CONSTRAINT `FKCE1004AD633BFFF9` FOREIGN KEY (`id_authority`) REFERENCES `authorities` (`id_authority`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

/*Data for the table `user_authorities` */
insert into `user_authorities` values
(1,1),
(2,2);

6 thoughts on “Hibernate based Spring Security Authentication in Web Application.

  1. I did the tutorial but i get this exception

    GRAVE: Failed to load jar:file:/D:/OctaveRefonte/workspace_1302/.metadata/.plugins/org.eclipse.wst.server.core/tmp0/wtpwebapps/HibernateAuthentication/WEB-INF/lib/zhtml-6.0.0.jar!/metainfo/zk/lang.xml
    org.zkoss.zk.device.DeviceNotFoundException: ajax pas trouvé.
    at org.zkoss.zk.ui.metainfo.LanguageDefinition.(LanguageDefinition.java:344)
    at org.zkoss.zk.ui.metainfo.DefinitionLoaders.parseLang(DefinitionLoaders.java:275)
    at org.zkoss.zk.ui.metainfo.DefinitionLoaders.load0(DefinitionLoaders.java:177)
    at org.zkoss.zk.ui.metainfo.DefinitionLoaders.load(DefinitionLoaders.java:153)
    at org.zkoss.zk.ui.metainfo.LanguageDefinition.init(LanguageDefinition.java:315)
    at org.zkoss.zk.ui.metainfo.LanguageDefinition.getAll(LanguageDefinition.java:294)
    at org.zkoss.zk.ui.http.WebManager.getCWRURLPrefix(WebManager.java:269)
    at org.zkoss.zk.ui.http.WebManager.(WebManager.java:226)
    at org.zkoss.zk.ui.http.DHtmlLayoutServlet.init(DHtmlLayoutServlet.java:102)
    at javax.servlet.GenericServlet.init(GenericServlet.java:160)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1228)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1147)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1043)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4957)
    at org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5284)
    at org.apache.catalina.core.StandardContext$3.call(StandardContext.java:5279)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:662)

    can someone help please?

  2. Hi Can we deploy same project in Spring framework and deploy to cloud foundry? I need to do a assignment – Spring + spring security + maven + hibernate.
    I am able to run the project by creating local database. Can you please let me know how to create the db inside Spring framework??

    I need to create a sample login application using spring and deploy to cloud foundry. And I’m new to spring and java..

  3. Hi,

    Thank you for this great tutorial!
    Juste one question. I think you have made a small mistake. Why you have added this : UNIQUE KEY `id_authority` (`id_authority`).

    Regards,
    Atif

  4. When I adding new user into users with ID=3 and want to add into user_authorities record (3,2) with ROLE_MEMBER, I have ERROR 1062 (23000): Duplicate entry ‘2’ for key ‘id_authority’

Leave a Reply to Java Project Cancel reply

Your email address will not be published. Required fields are marked *


3 − one =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>