diff --git a/pom.xml b/pom.xml
index 11d0141..085cd78 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,6 +74,7 @@
hibernate-search-examplespringmvc-springdata-mongodbspring-mongodb-tutorial
+ spring-security-tutorial
@@ -160,6 +161,12 @@
maven db plugin repositoryhttp://maven-db-plugin.googlecode.com/svn/maven/repodefault
+
+ true
+
+
+ false
+
@@ -230,11 +237,8 @@
-
-
-
@@ -349,7 +353,7 @@
2.14.1
-
+
org.apache.maven.pluginsmaven-pmd-plugin
@@ -388,7 +392,7 @@
2.3
-
+
org.codehaus.mojocobertura-maven-plugin
@@ -408,7 +412,7 @@
truefalse2.0
-
+
.settings/org.eclipse.core.resources.prefs
diff --git a/spring-security-tutorial/README b/spring-security-tutorial/README
new file mode 100644
index 0000000..8a1f18d
--- /dev/null
+++ b/spring-security-tutorial/README
@@ -0,0 +1,21 @@
+Description
+===========
+Sample application demonstrating how to implement a custom UserDetailsService with Spring Security 3.1 and Spring Data JPA
+
+To read the whole guide, please see the original blog:
+
+"Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA"
+http://krams915.blogspot.com/2012/01/spring-security-31-implement_5023.html
+
+
+Building
+========
+Please visit http://krams915.blogspot.com/2012/01/spring-security-31-implement.html for full instructions
+
+
+Notes
+=====
+For more tutorials, please visit http://krams915.blogspot.com/
+
+
+[https://github.com/krams915/spring-security-tutorial](https://github.com/krams915/spring-security-tutorial)
\ No newline at end of file
diff --git a/spring-security-tutorial/pom.xml b/spring-security-tutorial/pom.xml
new file mode 100644
index 0000000..9b6db2d
--- /dev/null
+++ b/spring-security-tutorial/pom.xml
@@ -0,0 +1,381 @@
+
+ 4.0.0
+
+ net.aimeizi
+ maven-framework-project
+ 1.0.0
+
+ spring-security-tutorial
+ war
+
+
+ UTF-8
+
+ 3.1.0.RELEASE
+ 3.1.0.RELEASE
+ 1.1.0.RELEASE
+
+ 2.2
+ 1.6.10
+
+ 5.1.16
+ 3.6.3.Final
+ 0.9.1.2
+
+ 2.2.5
+ 1.6.1
+ 1.2.14
+
+ 2.5
+ 1.1.2
+
+
+ 1.8.5
+ 4.8.2
+
+
+ 0.2.3
+ 2.3.2
+ 1.0
+
+
+
+
+
+ org.springframework
+ spring-core
+ ${spring.core.version}
+ jar
+ compile
+
+
+ org.springframework
+ spring-web
+ ${spring.core.version}
+ jar
+ compile
+
+
+ org.springframework
+ spring-tx
+ ${spring.core.version}
+ jar
+ compile
+
+
+ org.springframework
+ spring-webmvc
+ ${spring.core.version}
+ jar
+ compile
+
+
+ org.springframework
+ spring-jdbc
+ ${spring.core.version}
+ jar
+ compile
+
+
+ org.springframework
+ spring-oxm
+ ${spring.core.version}
+ jar
+ compile
+
+
+ org.springframework
+ spring-orm
+ ${spring.core.version}
+ jar
+ compile
+
+
+ org.springframework
+ spring-aspects
+ ${spring.core.version}
+ jar
+ compile
+
+
+
+
+ org.aspectj
+ aspectjrt
+ ${aspectj.version}
+
+
+
+ org.aspectj
+ aspectjweaver
+ ${aspectj.version}
+
+
+
+
+ cglib
+ cglib-nodep
+ ${cglib.version}
+ jar
+ compile
+
+
+
+
+ javax.servlet
+ jstl
+ ${javax.jstl-taglibs.version}
+
+
+ taglibs
+ standard
+ ${javax.jstl-taglibs.version}
+
+
+
+
+ log4j
+ log4j
+ ${log4j.version}
+ jar
+ compile
+
+
+
+
+ org.slf4j
+ slf4j-api
+ ${slf4j.version}
+ jar
+ compile
+
+
+ org.slf4j
+ slf4j-log4j12
+ ${slf4j.version}
+ jar
+ compile
+
+
+ org.slf4j
+ jcl-over-slf4j
+ ${slf4j.version}
+ jar
+ compile
+
+
+
+
+ org.springframework.security
+ spring-security-core
+ ${spring.security.core.version}
+ jar
+ compile
+
+
+ org.springframework.security
+ spring-security-web
+ ${spring.security.core.version}
+ jar
+ compile
+
+
+ org.springframework.security
+ spring-security-config
+ ${spring.security.core.version}
+ jar
+ compile
+
+
+ org.springframework.security
+ spring-security-taglibs
+ ${spring.security.core.version}
+ jar
+ compile
+
+
+
+
+ org.springframework.data
+ spring-data-jpa
+ ${spring.data.jpa.version}
+
+
+ org.springframework
+ spring-orm
+
+
+
+
+
+
+ c3p0
+ c3p0
+ ${c3p0.version}
+ jar
+ compile
+
+
+
+
+ mysql
+ mysql-connector-java
+ ${mysql.connector.version}
+ jar
+ compile
+
+
+
+
+ org.hibernate.javax.persistence
+ hibernate-jpa-2.0-api
+ 1.0.1.Final
+
+
+ org.hibernate
+ hibernate-entitymanager
+ ${hibernate.entitymanager.version}
+ compile
+
+
+
+
+ com.mysema.querydsl
+ querydsl-core
+ ${querydsl.version}
+ jar
+ compile
+
+
+ com.mysema.querydsl
+ querydsl-jpa
+ ${querydsl.version}
+ jar
+ compile
+
+
+ com.mysema.querydsl
+ querydsl-apt
+ ${querydsl.version}
+ provided
+
+
+
+
+ javax.servlet
+ servlet-api
+ ${javax.servlet-api.version}
+ provided
+
+
+
+
+ junit
+ junit
+ ${junit.version}
+ jar
+ test
+
+
+ org.mockito
+ mockito-all
+ ${mockito.version}
+ jar
+ test
+
+
+ org.springframework
+ spring-test
+ ${spring.core.version}
+ jar
+ test
+
+
+
+
+
+ spring-security-tutorial
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven.compiler.plugin.version}
+
+ 1.6
+ 1.6
+
+
+
+
+ org.mortbay.jetty
+ jetty-maven-plugin
+ 7.6.5.v20120716
+
+
+
+
+ maven-resources-plugin
+ 2.5
+
+
+ copy-meta-inf
+ compile
+
+ copy-resources
+
+
+ ${project.build.outputDirectory}/META-INF
+
+
+ ${project.basedir}/src/main/java/META-INF
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ org.springframework.maven.release
+ Spring Maven Release Repository
+ http://maven.springframework.org/release
+
+ true
+
+
+ false
+
+
+
+
+
+ org.springframework.maven.milestone
+ Spring Maven Milestone Repository
+ http://maven.springframework.org/milestone
+
+ false
+
+
+
+
+ jboss
+ JBoss repository
+ https://repository.jboss.org/nexus/content/repositories/releases
+
+
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/java/META-INF/orm.xml b/spring-security-tutorial/src/main/java/META-INF/orm.xml
new file mode 100644
index 0000000..aa5d1e7
--- /dev/null
+++ b/spring-security-tutorial/src/main/java/META-INF/orm.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/spring-security-tutorial/src/main/java/META-INF/persistence.xml b/spring-security-tutorial/src/main/java/META-INF/persistence.xml
new file mode 100644
index 0000000..675b55b
--- /dev/null
+++ b/spring-security-tutorial/src/main/java/META-INF/persistence.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+ META-INF/orm.xml
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/java/org/krams/aop/TraceInterceptor.java b/spring-security-tutorial/src/main/java/org/krams/aop/TraceInterceptor.java
new file mode 100644
index 0000000..0602ed7
--- /dev/null
+++ b/spring-security-tutorial/src/main/java/org/krams/aop/TraceInterceptor.java
@@ -0,0 +1,29 @@
+package org.krams.aop;
+
+import org.aopalliance.intercept.MethodInvocation;
+import org.apache.commons.logging.Log;
+import org.apache.log4j.Logger;
+import org.springframework.aop.interceptor.CustomizableTraceInterceptor;
+
+/**
+ * Extends {@link CustomizableTraceInterceptor} to provide custom logging levels
+ */
+public class TraceInterceptor extends CustomizableTraceInterceptor {
+
+ private static final long serialVersionUID = 287162721460370957L;
+ protected static Logger logger4J = Logger.getLogger("aop");
+
+ @Override
+ protected void writeToLog(Log logger, String message, Throwable ex) {
+ if (ex != null) {
+ logger4J.debug(message, ex);
+ } else {
+ logger4J.debug(message);
+ }
+ }
+
+ @Override
+ protected boolean isInterceptorEnabled(MethodInvocation invocation, Log logger) {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/java/org/krams/controller/AccessController.java b/spring-security-tutorial/src/main/java/org/krams/controller/AccessController.java
new file mode 100644
index 0000000..06ccd3d
--- /dev/null
+++ b/spring-security-tutorial/src/main/java/org/krams/controller/AccessController.java
@@ -0,0 +1,34 @@
+package org.krams.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+@Controller
+@RequestMapping
+public class AccessController {
+
+ @RequestMapping("/login")
+ public String login(Model model, @RequestParam(required=false) String message) {
+ model.addAttribute("message", message);
+ return "access/login";
+ }
+
+ @RequestMapping(value = "/denied")
+ public String denied() {
+ return "access/denied";
+ }
+
+ @RequestMapping(value = "/login/failure")
+ public String loginFailure() {
+ String message = "Login Failure!";
+ return "redirect:/login?message="+message;
+ }
+
+ @RequestMapping(value = "/logout/success")
+ public String logoutSuccess() {
+ String message = "Logout Success!";
+ return "redirect:/login?message="+message;
+ }
+}
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/java/org/krams/controller/MediatorController.java b/spring-security-tutorial/src/main/java/org/krams/controller/MediatorController.java
new file mode 100644
index 0000000..f425431
--- /dev/null
+++ b/spring-security-tutorial/src/main/java/org/krams/controller/MediatorController.java
@@ -0,0 +1,24 @@
+package org.krams.controller;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+@Controller
+@RequestMapping("/")
+public class MediatorController {
+
+ @RequestMapping
+ public String getHomePage() {
+ return "home";
+ }
+
+ @RequestMapping(value="/user")
+ public String getUserPage() {
+ return "user";
+ }
+
+ @RequestMapping(value="/admin")
+ public String getAdminPage() {
+ return "admin";
+ }
+}
diff --git a/spring-security-tutorial/src/main/java/org/krams/domain/Role.java b/spring-security-tutorial/src/main/java/org/krams/domain/Role.java
new file mode 100644
index 0000000..f680418
--- /dev/null
+++ b/spring-security-tutorial/src/main/java/org/krams/domain/Role.java
@@ -0,0 +1,35 @@
+package org.krams.domain;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+@Entity(name="role")
+public class Role {
+
+ @Id
+ private Long id;
+
+ @OneToOne
+ private User user;
+ private Integer role;
+
+ public Long getId() {
+ return id;
+ }
+ public void setId(Long id) {
+ this.id = id;
+ }
+ public User getUser() {
+ return user;
+ }
+ public void setUser(User user) {
+ this.user = user;
+ }
+ public Integer getRole() {
+ return role;
+ }
+ public void setRole(Integer role) {
+ this.role = role;
+ }
+}
diff --git a/spring-security-tutorial/src/main/java/org/krams/domain/User.java b/spring-security-tutorial/src/main/java/org/krams/domain/User.java
new file mode 100644
index 0000000..defcd64
--- /dev/null
+++ b/spring-security-tutorial/src/main/java/org/krams/domain/User.java
@@ -0,0 +1,72 @@
+package org.krams.domain;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+
+@Entity(name="user")
+public class User {
+
+ @Id
+ private Long id;
+
+ private String firstName;
+ private String lastName;
+
+ @Column(unique=true)
+ private String username;
+ private String password;
+
+ @OneToOne(mappedBy="user", cascade={CascadeType.ALL})
+ private Role role;
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ 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 Role getRole() {
+ return role;
+ }
+
+ public void setRole(Role role) {
+ this.role = role;
+ }
+}
diff --git a/spring-security-tutorial/src/main/java/org/krams/repository/UserRepository.java b/spring-security-tutorial/src/main/java/org/krams/repository/UserRepository.java
new file mode 100644
index 0000000..09f69bc
--- /dev/null
+++ b/spring-security-tutorial/src/main/java/org/krams/repository/UserRepository.java
@@ -0,0 +1,9 @@
+package org.krams.repository;
+
+import org.krams.domain.User;
+import org.springframework.data.jpa.repository.JpaRepository;
+
+public interface UserRepository extends JpaRepository {
+
+ User findByUsername(String username);
+}
diff --git a/spring-security-tutorial/src/main/java/org/krams/service/CustomUserDetailsService.java b/spring-security-tutorial/src/main/java/org/krams/service/CustomUserDetailsService.java
new file mode 100644
index 0000000..d106eda
--- /dev/null
+++ b/spring-security-tutorial/src/main/java/org/krams/service/CustomUserDetailsService.java
@@ -0,0 +1,97 @@
+package org.krams.service;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.krams.repository.UserRepository;
+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.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * A custom {@link UserDetailsService} where user information
+ * is retrieved from a JPA repository
+ */
+@Service
+@Transactional(readOnly = true)
+public class CustomUserDetailsService implements UserDetailsService {
+
+ @Autowired
+ private UserRepository userRepository;
+
+ /**
+ * Returns a populated {@link UserDetails} object.
+ * The username is first retrieved from the database and then mapped to
+ * a {@link UserDetails} object.
+ */
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+ try {
+ org.krams.domain.User domainUser = userRepository.findByUsername(username);
+
+ boolean enabled = true;
+ boolean accountNonExpired = true;
+ boolean credentialsNonExpired = true;
+ boolean accountNonLocked = true;
+
+ return new User(
+ domainUser.getUsername(),
+ domainUser.getPassword().toLowerCase(),
+ enabled,
+ accountNonExpired,
+ credentialsNonExpired,
+ accountNonLocked,
+ getAuthorities(domainUser.getRole().getRole()));
+
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Retrieves a collection of {@link GrantedAuthority} based on a numerical role
+ * @param role the numerical role
+ * @return a collection of {@link GrantedAuthority
+ */
+ public Collection extends GrantedAuthority> getAuthorities(Integer role) {
+ List authList = getGrantedAuthorities(getRoles(role));
+ return authList;
+ }
+
+ /**
+ * Converts a numerical role to an equivalent list of roles
+ * @param role the numerical role
+ * @return list of roles as as a list of {@link String}
+ */
+ public List getRoles(Integer role) {
+ List roles = new ArrayList();
+
+ if (role.intValue() == 1) {
+ roles.add("ROLE_USER");
+ roles.add("ROLE_ADMIN");
+
+ } else if (role.intValue() == 2) {
+ roles.add("ROLE_USER");
+ }
+
+ return roles;
+ }
+
+ /**
+ * Wraps {@link String} roles to {@link SimpleGrantedAuthority} objects
+ * @param roles {@link String} of roles
+ * @return list of granted authorities
+ */
+ public static List getGrantedAuthorities(List roles) {
+ List authorities = new ArrayList();
+ for (String role : roles) {
+ authorities.add(new SimpleGrantedAuthority(role));
+ }
+ return authorities;
+ }
+}
diff --git a/spring-security-tutorial/src/main/resources/log4j.properties b/spring-security-tutorial/src/main/resources/log4j.properties
new file mode 100644
index 0000000..aa7c40b
--- /dev/null
+++ b/spring-security-tutorial/src/main/resources/log4j.properties
@@ -0,0 +1,14 @@
+log4j.rootLogger=DEBUG,console
+
+#Console Appender
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=[%5p] [%t %d{hh:mm:ss}] (%F:%M:%L) %m%n
+
+#Custom assignments
+log4j.logger.controller=DEBUG,console
+log4j.logger.service=DEBUG,console
+
+#Disable additivity
+log4j.additivity.controller=false
+log4j.additivity.service=false
diff --git a/spring-security-tutorial/src/main/resources/spring_security_tutorial.sql b/spring-security-tutorial/src/main/resources/spring_security_tutorial.sql
new file mode 100644
index 0000000..473a125
--- /dev/null
+++ b/spring-security-tutorial/src/main/resources/spring_security_tutorial.sql
@@ -0,0 +1,76 @@
+-- phpMyAdmin SQL Dump
+-- version 3.3.9
+-- http://www.phpmyadmin.net
+--
+-- Host: localhost
+-- Generation Time: Jan 09, 2012 at 06:08 PM
+-- Server version: 5.5.8
+-- PHP Version: 5.3.5
+
+SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
+
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+
+--
+-- Database: `spring_security_tutorial`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `role`
+--
+
+CREATE TABLE IF NOT EXISTS `role` (
+ `id` bigint(20) NOT NULL,
+ `role` int(11) DEFAULT NULL,
+ `user_id` bigint(20) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `FK3580769128426C` (`user_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `role`
+--
+
+INSERT INTO `role` (`id`, `role`, `user_id`) VALUES
+(1, 1, 1),
+(2, 2, 2);
+
+-- --------------------------------------------------------
+
+--
+-- Table structure for table `user`
+--
+
+CREATE TABLE IF NOT EXISTS `user` (
+ `id` bigint(20) NOT NULL,
+ `firstName` varchar(255) DEFAULT NULL,
+ `lastName` varchar(255) DEFAULT NULL,
+ `password` varchar(255) DEFAULT NULL,
+ `username` varchar(255) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `username` (`username`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1;
+
+--
+-- Dumping data for table `user`
+--
+
+INSERT INTO `user` (`id`, `firstName`, `lastName`, `password`, `username`) VALUES
+(1, 'John', 'Smith', '21232f297a57a5a743894a0e4a801fc3', 'john'),
+(2, 'Jane', 'Adams', 'ee11cbb19052e40b07aac0ca060c23ee', 'jane');
+
+--
+-- Constraints for dumped tables
+--
+
+--
+-- Constraints for table `role`
+--
+ALTER TABLE `role`
+ ADD CONSTRAINT `FK3580769128426C` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`);
diff --git a/spring-security-tutorial/src/main/webapp/META-INF/MANIFEST.MF b/spring-security-tutorial/src/main/webapp/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..254272e
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/applicationContext.xml b/spring-security-tutorial/src/main/webapp/WEB-INF/applicationContext.xml
new file mode 100644
index 0000000..e9f360b
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/applicationContext.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/access/denied.jsp b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/access/denied.jsp
new file mode 100644
index 0000000..f1c4ed5
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/access/denied.jsp
@@ -0,0 +1,16 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ page import="org.springframework.security.core.context.SecurityContextHolder" %>
+
+
+
+ Home
+
+
+
+
+
Unauthorized
+
+
+
Access denied!
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/access/login.jsp b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/access/login.jsp
new file mode 100644
index 0000000..f5ba830
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/access/login.jsp
@@ -0,0 +1,37 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
+<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
+
+
+
+
+ Login
+
+
+
+
+
${message}
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/admin.jsp b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/admin.jsp
new file mode 100644
index 0000000..df6da04
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/admin.jsp
@@ -0,0 +1,25 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+
+
+ Admin
+
+
+
+
+
Admin
+
+
+
Only admins can see this page
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et velit et sem
+ fermentum viverra. Duis fringilla consequat lectus, et rhoncus mauris porta ut. Cum
+ sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+ Donec commodo lorem sed felis iaculis pretium. Cras vel scelerisque ipsum.
+ Donec a lacus lectus, ac dignissim dui. Duis vel dui et lacus dapibus lacinia. Mauris
+ lacus metus, semper in varius vitae, ornare at augue. Nam enim elit, iaculis iaculis
+ viverra at, blandit quis turpis. Nulla turpis quam, suscipit sed pellentesque sit amet,
+ fermentum nec mauris. In non urna ornare sem cursus luctus. Pellentesque sed leo
+ elit. Duis ut felis dui, et mollis nibh. Suspendisse faucibus molestie feugiat. Pellentesque
+ non velit blandit ipsum auctor tempor placerat a eros. Quisque nec porttitor velit.
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/home.jsp b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/home.jsp
new file mode 100644
index 0000000..f68333e
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/home.jsp
@@ -0,0 +1,26 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ page import="org.springframework.security.core.context.SecurityContextHolder" %>
+
+
+
+ Home
+
+
+
+
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et velit et sem
+ fermentum viverra. Duis fringilla consequat lectus, et rhoncus mauris porta ut. Cum
+ sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+ Donec commodo lorem sed felis iaculis pretium. Cras vel scelerisque ipsum.
+ Donec a lacus lectus, ac dignissim dui. Duis vel dui et lacus dapibus lacinia. Mauris
+ lacus metus, semper in varius vitae, ornare at augue. Nam enim elit, iaculis iaculis
+ viverra at, blandit quis turpis. Nulla turpis quam, suscipit sed pellentesque sit amet,
+ fermentum nec mauris. In non urna ornare sem cursus luctus. Pellentesque sed leo
+ elit. Duis ut felis dui, et mollis nibh. Suspendisse faucibus molestie feugiat. Pellentesque
+ non velit blandit ipsum auctor tempor placerat a eros. Quisque nec porttitor velit.
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/menu.jsp b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/menu.jsp
new file mode 100644
index 0000000..5496667
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/menu.jsp
@@ -0,0 +1,24 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
+<%@ taglib uri="http://www.springframework.org/tags" prefix="spring" %>
+<%@ page import="org.springframework.security.core.context.SecurityContextHolder" %>
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/user.jsp b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/user.jsp
new file mode 100644
index 0000000..0103822
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/jsp/user.jsp
@@ -0,0 +1,25 @@
+<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
+
+
+
+ User
+
+
+
+
+
User
+
+
+
All users can see this page
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean et velit et sem
+ fermentum viverra. Duis fringilla consequat lectus, et rhoncus mauris porta ut. Cum
+ sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
+ Donec commodo lorem sed felis iaculis pretium. Cras vel scelerisque ipsum.
+ Donec a lacus lectus, ac dignissim dui. Duis vel dui et lacus dapibus lacinia. Mauris
+ lacus metus, semper in varius vitae, ornare at augue. Nam enim elit, iaculis iaculis
+ viverra at, blandit quis turpis. Nulla turpis quam, suscipit sed pellentesque sit amet,
+ fermentum nec mauris. In non urna ornare sem cursus luctus. Pellentesque sed leo
+ elit. Duis ut felis dui, et mollis nibh. Suspendisse faucibus molestie feugiat. Pellentesque
+ non velit blandit ipsum auctor tempor placerat a eros. Quisque nec porttitor velit.
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/spring-data.xml b/spring-security-tutorial/src/main/webapp/WEB-INF/spring-data.xml
new file mode 100644
index 0000000..52d7a4c
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/spring-data.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/spring-security.xml b/spring-security-tutorial/src/main/webapp/WEB-INF/spring-security.xml
new file mode 100644
index 0000000..ea357ac
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/spring-security.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/spring-servlet.xml b/spring-security-tutorial/src/main/webapp/WEB-INF/spring-servlet.xml
new file mode 100644
index 0000000..6147bea
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/spring-servlet.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/spring.properties b/spring-security-tutorial/src/main/webapp/WEB-INF/spring.properties
new file mode 100644
index 0000000..43a0a41
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/spring.properties
@@ -0,0 +1,5 @@
+# database properties
+app.jdbc.driverClassName=com.mysql.jdbc.Driver
+app.jdbc.url=jdbc\:mysql\://localhost/spring_security_tutorial
+app.jdbc.username=root
+app.jdbc.password=
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/trace-context.xml b/spring-security-tutorial/src/main/webapp/WEB-INF/trace-context.xml
new file mode 100644
index 0000000..61ab0ee
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/trace-context.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-security-tutorial/src/main/webapp/WEB-INF/web.xml b/spring-security-tutorial/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..0f6e172
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,37 @@
+
+
+ Spring Security Tutorial
+
+
+ springSecurityFilterChain
+ org.springframework.web.filter.DelegatingFilterProxy
+
+
+
+ springSecurityFilterChain
+ /*
+
+
+
+ contextConfigLocation
+
+ /WEB-INF/spring-security.xml
+ /WEB-INF/applicationContext.xml
+
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
+ spring
+ org.springframework.web.servlet.DispatcherServlet
+
+
+
+ spring
+ /
+
+
+
diff --git a/spring-security-tutorial/src/main/webapp/resources/css/style.css b/spring-security-tutorial/src/main/webapp/resources/css/style.css
new file mode 100644
index 0000000..636163e
--- /dev/null
+++ b/spring-security-tutorial/src/main/webapp/resources/css/style.css
@@ -0,0 +1,98 @@
+body {
+ font-family: Arial, sans-serif;
+ width: 500px;
+ margin: auto;
+}
+
+h1, hr {
+ margin: 0px;
+ padding: 0px;
+}
+
+#banner {
+ display: block;
+}
+
+#username {
+ color: red;
+ font-weight: bold;
+}
+
+#menu-username {
+ color: red;
+ float: right;
+ margin-top: 10px;
+ margin-right: 10px;
+}
+
+.message {
+ color: red;
+ text-align: center;
+}
+
+.login-form {
+ background-color: #333;
+ color: white;
+ padding: 5px;
+ width: 300px;
+ height: 220px;
+ margin: auto;
+ text-align: center;
+ margin-top: 100px;
+}
+
+.login-form fieldset {
+ border: 1px solid gray;
+}
+
+.login-form legend {
+ margin: 0px;
+ padding: 0px;
+ text-align: left;
+}
+
+.login-form hr {
+ height: 1px;
+ border: 0px;
+ border-top: 1px solid black;
+}
+
+.login-form input {
+ /*float: right;*/
+}
+
+/**
+* Menu based on James Owers' Horizontal CSS List Menu
+* @see http://jamesowers.co.uk/css-tutorials/50/horizontal-css-list-menu/
+*/
+.menu {
+ width: 100%;
+ background-color: #333;
+}
+
+.menu ul {
+ margin: 0;
+ padding: 0;
+ float: left;
+}
+
+.menu ul li {
+ display: inline;
+}
+
+.menu ul li a {
+ float: left;
+ text-decoration: none;
+ color: white;
+ padding: 10.5px 11px;
+ background-color: #333;
+}
+
+.menu ul li a:visited {
+ color: white;
+}
+
+.menu ul li a:hover, .menu ul li .current {
+ color: #fff;
+ background-color:#0b75b2;
+}
\ No newline at end of file