Вы находитесь на странице: 1из 35

Database Setup for Spring Security and Hibernate Integration

Before we go forward let's first create a database and required tables to store and get user
credential from, we have created two tables "users" and "user_roles". We have added
two users details, with ROLE_USER and ROLE_ADMIN to be used here. Just copy and
execute the below script in your mysql query editor to get a db setup for you.

-- Dumping database structure for spring_social_db


CREATE DATABASE IF NOT EXISTS `spring_social_db` /*!40100 DEFAULT
CHARACTER SET latin1 */;
USE `spring_social_db`;

-- Dumping structure for table spring_social_db.users


CREATE TABLE IF NOT EXISTS `users` (
`username` varchar(45) NOT NULL,
`enabled` bit(1) NOT NULL,
`password` varchar(60) NOT NULL,
PRIMARY KEY (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

-- Dumping data for table spring_social_db.users: ~2 rows


(approximately)
/*!40000 ALTER TABLE `users` DISABLE KEYS */;
INSERT INTO `users` (`username`, `enabled`, `password`) VALUES
('admin', b'10000000', 'admin@123'),
('user', b'10000000', 'user@123');

/*!40000 ALTER TABLE `users` ENABLE KEYS */;

-- Dumping structure for table spring_social_db.user_roles


CREATE TABLE IF NOT EXISTS `user_roles` (
`user_role_id` int(11) NOT NULL AUTO_INCREMENT,
`role` varchar(45) NOT NULL,
`username` varchar(45) NOT NULL,
PRIMARY KEY (`user_role_id`),
KEY `FK_9ry105icat2dux14oyixybw9l` (`username`),
CONSTRAINT `FK_9ry105icat2dux14oyixybw9l` FOREIGN KEY
(`username`) REFERENCES `users` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

-- Dumping data for table spring_social_db.user_roles: ~3 rows


(approximately)
/*!40000 ALTER TABLE `user_roles` DISABLE KEYS */;
INSERT INTO `user_roles` (`user_role_id`, `role`, `username`)
VALUES
(1, 'ROLE_ADMIN', 'admin'),
(2, 'ROLE_USER', 'user'),
(3, 'ROLE_USER', 'admin');
/*!40000 ALTER TABLE `user_roles` ENABLE KEYS */;
/*!40014 SET FOREIGN_KEY_CHECKS=1 */;

/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;

If everything goes right you will see following table structures.

Dependencies required for Spring Security with Hibernate


integration
pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.beingjavaguys.sample</groupId>
<artifactId>SP_SC_Hibernate</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>SP_SC_Hibernate Maven Webapp</name>
<url>http://maven.apache.org</url>
<properties>
<spring.version>4.0.6.RELEASE</spring.version>
<hibernate.version>4.3.6.Final</hibernate.version>

<log4j.version>1.2.17</log4j.version>
<jdk.version>1.7</jdk.version>
<jstl.version>1.2</jstl.version>
<mysql_connector.version>5.1.6</mysql_connector.version>
<spring.security.version>3.2.5.RELEASE</spring.security.version>
<context.path>SP_SC_Hibernate</context.path>
</properties>
<build>
<finalName>${pom.artifactId}</finalName>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>

<!-- hibernate -->


<dependency>

<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>

<!-- log4j -->


<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j.version}</version>
</dependency>

<!-- Spring -->


<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>

<!-- Spring Security -->


<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>

<!-- Spring Security JSP Taglib -->


<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>${spring.security.version}</version>
</dependency>

<!-- jstl -->


<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>

<!-- mysql driver -->


<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql_connector.version}</version>
</dependency>
</dependencies>
</project>

\src\main\webapp\WEB-INF\web.xml
We need to make an Spring entry to web.xml, this will tell the container that all upcoming
requests will be served by Spring Framework itself as per the configuration. We have also
added a filter entry to integrate spring security in the application.
<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">

<display-name>Sample Spring Maven Project</display-name>


<!-- Spring MVC -->

<servlet>
<servlet-name>mvc-dispatcher</servlet-name>
<servletclass>org.springframework.web.servlet.DispatcherServlet</servletclass>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>mvc-dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<listener>

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

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/mvc-dispatcher-servlet.xml,
/WEB-INF/spring-security.xml
</param-value>

</context-param>

<!-- Spring Security -->

<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filterclass>org.springframework.web.filter.DelegatingFilterProxy</filterclass>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>

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

</web-app>

\src\main\webapp\WEB-INF\spring-config.xml
This is simple spring configuration file, we have added entry for base-package here to
search and find Controller, Dao and Service classes with annotations. We defined few
beans here for hibernate configurations and a datasource bean to connect with database.
More details on : Spring Hibernate Integration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-3.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context3.2.xsd">

<context:component-scan base-package="com.beingjavaguys" />


<context:property-placeholder
location="classpath:database.properties" />

<mvc:resources mapping="/resources/**" location="/resources/" />


<mvc:annotation-driven />

<bean id="dataSource"

class="org.springframework.jdbc.datasource.DriverManagerDataSource"
>
<property name="driverClassName" value="${database.driver}" />
<property name="url" value="${database.url}" />
<property name="username" value="${database.user}" />
<property name="password" value="${database.password}" />
</bean>

<bean id="sessionFactory"

class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.beingjavaguys.models.login.Users</value>
<value>com.beingjavaguys.models.login.UserRole</value>
</list>
</property>
<property name="hibernateProperties">

<props>
<prop
key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
</props>
</property>
</bean>

<bean id="txManager"

class="org.springframework.orm.hibernate4.HibernateTransactionManag
er">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="persistenceExceptionTranslationPostProcessor"

class="org.springframework.dao.annotation.PersistenceExceptionTrans
lationPostProcessor" />

<bean

class="org.springframework.web.servlet.view.InternalResourceViewRes
olver">
<property name="prefix">

<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>

Spring security configuration file


\src\main\webapp\WEB-INF\spring-security.xml
Here is spring-security configuration file with all required configurations and settings, we
have defioned two roles here and a service "loginService" bean to communicate with data
layer of the application.
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security3.2.xsd">

<!-- enable use-expressions -->


<http auto-config="true" use-expressions="true">
<intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')"
/>
<intercept-url pattern="/user**" access="hasRole('ROLE_USER')" />

<!-- access denied page -->


<access-denied-handler error-page="/403" />
<form-login login-page="/login" authentication-failureurl="/login?error"
username-parameter="username" password-parameter="password" />
<logout logout-success-url="/login?logout" />
<!-- enable csrf protection -->
<csrf />
</http>

<authentication-manager>
<authentication-provider user-service-ref="loginService" />
</authentication-manager>

</beans:beans>

Login controller code


\src\main\java\com\beingjavaguys\controller\LoginController.java
This is simple spring mvc controller having request mappings to deal with different
incoming request and render appropriate pages used in the login process.
package com.beingjavaguys.controller;
import
org.springframework.security.authentication.AnonymousAuthentication
Token;
import org.springframework.security.core.Authentication;

import
org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;

import com.beingjavaguys.models.login.Users;

@Controller
public class LoginController {

@RequestMapping(value = { "/", "/home" })


public String getUserDefault() {
return "home";
}

@RequestMapping("/login")
public ModelAndView getLoginForm(@ModelAttribute Users users,
@RequestParam(value = "error", required = false) String error,
@RequestParam(value = "logout", required = false) String logout)
{

String message = "";


if (error != null) {
message = "Incorrect username or password !";
} else if (logout != null) {
message = "Logout successful !";
}
return new ModelAndView("login", "message", message);
}

@RequestMapping("/admin**")
public String getAdminProfile() {
return "admin";
}

@RequestMapping("/user**")
public String getUserProfile() {
return "user";
}

@RequestMapping("/403")
public ModelAndView getAccessDenied() {
Authentication auth = SecurityContextHolder.getContext()

.getAuthentication();
String username = "";
if (!(auth instanceof AnonymousAuthenticationToken)) {
UserDetails userDetail = (UserDetails) auth.getPrincipal();
username = userDetail.getUsername();
}

return new ModelAndView("403", "username", username);


}

Model classes to represent "user" and "user_role" tables in


database
\src\main\java\com\beingjavaguys\models\login\Users.java

package com.beingjavaguys.models.login;

import java.util.HashSet;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;

import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name = "users", catalog = "spring_social_db")
public class Users {

@Id
@Column(name = "username", unique = true, nullable = false, length
= 45)
private String username;

@Column(name = "password", nullable = false, length = 60)


private String password;

@Column(name = "enabled", nullable = false)


private boolean enabled;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "user")


private Set userRole = new HashSet(0);

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 boolean isEnabled() {


return enabled;
}

public void setEnabled(boolean enabled) {


this.enabled = enabled;

public Set getUserRole() {


return userRole;
}

public void setUserRole(Set userRole) {


this.userRole = userRole;
}
}

\src\main\java\com\beingjavaguys\models\login\UserRole.java
package com.beingjavaguys.models.login;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name = "user_roles", catalog = "spring_social_db")
public class UserRole {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "user_role_id", unique = true, nullable = false)
private Integer userRoleId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "username", nullable = false)
private Users user;

@Column(name = "role", nullable = false, length = 45)


private String role;

public Integer getUserRoleId() {


return userRoleId;
}

public void setUserRoleId(Integer userRoleId) {


this.userRoleId = userRoleId;

public Users getUser() {


return user;
}

public void setUser(Users user) {


this.user = user;
}

public String getRole() {


return role;
}

public void setRole(String role) {


this.role = role;
}

Data Layer for Spring Security and Hibernate Configuration


\src\main\java\com\beingjavaguys\dao\login\LoginDao.java

package com.beingjavaguys.dao.login;

import com.beingjavaguys.models.login.Users;

public interface LoginDao {


Users findByUserName(String username);
}

\src\main\java\com\beingjavaguys\dao\login\LoginDaoImpl.java
package com.beingjavaguys.dao.login;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.beingjavaguys.models.login.Users;

@Repository("loginDao")
public class LoginDaoImpl implements LoginDao{

@Autowired
SessionFactory sessionFactory;

Session session = null;


Transaction tx = null;

@Override
public Users findByUserName(String username) {
session = sessionFactory.openSession();
tx = session.getTransaction();
session.beginTransaction();
Users user = (Users) session.load(Users.class, new
String(username));
tx.commit();
return user;
}

\src\main\java\com\beingjavaguys\service\login\LoginServiceImpl.java
package com.beingjavaguys.service.login;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import
org.springframework.security.core.authority.SimpleGrantedAuthority;
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.UsernameNotFoundExcep
tion;
import org.springframework.stereotype.Service;

import com.beingjavaguys.dao.login.LoginDao;
import com.beingjavaguys.models.login.UserRole;
import com.beingjavaguys.models.login.Users;

@Service("loginService")
public class LoginServiceImpl implements UserDetailsService {

@Autowired
LoginDao loginDao;

@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException {

Users user = loginDao.findByUserName(username);

List authorities = buildUserAuthority(user


.getUserRole());

return buildUserForAuthentication(user, authorities);


}

private User buildUserForAuthentication(Users user,


List authorities) {
return new User(user.getUsername(), user.getPassword(),
user.isEnabled(), true, true, true, authorities);
}

private List buildUserAuthority(Set userRoles) {

Set setAuths = new HashSet();

// Build user's authorities


for (UserRole userRole : userRoles) {
setAuths.add(new SimpleGrantedAuthority(userRole.getRole()));
}

List Result = new ArrayList(


setAuths);

return Result;
}

Front End Layer files


Login Form \src\main\webapp\WEB-INF\pages\login.jsp
<%@taglib uri="http://www.springframework.org/tags/form"
prefix="form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Login | Beingjavaguys.com</title>

</head>
<body>
<center>
<br /> <br /> <br />
<div style="border: 1px solid black; width: 300px; padding-top:
10px;">
<br /> Please enter your username and password to login ! <br />
<span
style="color: red">${message}</span> <br />
<form:form method="post" action="j_spring_security_check"
modelAttribute="users">
<table>
<tr>
<td>Username:</td>
<td><form:input path="username" /></td>
</tr>
<tr>
<td>Password:</td>
<td><form:input path="password" /></td>
</tr>
<tr>
<td> </td>
<td><input type="submit" /></td>
</tr>

</table>
</form:form>
</div>
</center>

</body>
</html>

\src\main\webapp\WEB-INF\pages\home.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Home Page | Beingjavaguys.com</title>
</head>
<body>
<center>
<br /> <br /> <br />
<h1>Default Logged in User page !!!</h1>
<c:url var="logoutUrl" value="j_spring_security_logout" />
<form action="${logoutUrl}" method="post">
<input type="submit" value="Log out" /> <input type="hidden"
name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</center>

</body>
</html>

\src\main\webapp\WEB-INF\pages\admin.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>Admin Profile Page | Beingjavaguys.com</title>
</head>
<body>
<center>
<br /> <br /> <br />
<h1>Admin profile page !!!</h1>
<c:url var="logoutUrl" value="j_spring_security_logout" />
<form action="${logoutUrl}" method="post">
<input type="submit" value="Log out" /> <input type="hidden"
name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</center>

</body>
</html>

\src\main\webapp\WEB-INF\pages\user.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head>
<title>User Profile Page | Beingjavaguys.com</title>
</head>
<body>
<center>
<br /> <br /> <br />
<h1>User profile page !!!</h1>
<c:url var="logoutUrl" value="j_spring_security_logout" />
<form action="${logoutUrl}" method="post">
<input type="submit" value="Log out" /> <input type="hidden"
name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</center>

</body>
</html>

\src\main\webapp\WEB-INF\pages\403.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>

<head>
<title>Access Denied | Beingjavaguys.com</title>
</head>
<body>
<center>
<br /> <br /> <br />
<h1>
Access Denied for User : <span style="color:
red;">${username}</span>
</h1>
<c:url var="logoutUrl" value="j_spring_security_logout" />
<form action="${logoutUrl}" method="post">
<input type="submit" value="Log out" /> <input type="hidden"
name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</center>

</body>
</html>

How to run the application


Once you are donw with adding all required file to the project, simple run the application on
server and hit following URL: http://localhost:8080/SP_SC_Hibernate/user
It will redirect you to login page (http://localhost:8080/SP_SC_Hibernate/login)

Enter the user credentials "user"/"user@123", and you will get your requested page after
a success login:

Now try to see admin page, hit url http://localhost:8080/SP_SC_Hibernate/admin


Now you will get a access denied error, because "user" is not authorized to
see "/admin"pages.

That's all for now in, Spring Security with Hibernate with Maven.

Вам также может понравиться