Friday, January 13, 2012

Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 2)

Review

In the previous section, we have laid down the functional specs of the application. In this section, we will discuss the project's structure, write the Java classes, and organize them in layers.


Project Structure

Our application is a Maven project and therefore follows Maven structure. As we create the classes, we've organized them in logical layers: domain, repository, service, and controller.

Here's a preview of our project's structure:

The Layers

Domain Layer

This layer contains two domain classes, User and Role. They represent our database tables, user and role respectively. Because we're developing a JPA-based repository, both classes must be annotated with JPA annotations.




Specifying the entity name inside the @Entity is not required. However, I've encountered instances where the tables are created in lowercase and uppercase, i.e user and USER. For consistency, I've specified them here.

Controller Layer

This layer contains two controllers, AccessController and MediatorController.
  • AccessController is responsible for handling access related requests, mainly login and logout requests
  • MediatorController is responsible for handling requests to common pages such as user and admin pages




Service Layer

This layer contains a single service, CustomUserDetailsService. Its main purpose is to retrieve user information from our custom database and translate that user information into a format that Spring Security understands. Take note of the helper methods provided within this class.



What's the logic here?
  1. We must implement UserDetailsService because we have a custom database
  2. loadUserByUsername method must return an object that implements the UserDetails interface
  3. We must map our domain org.krams.domain.User to org.springframework.security.core.userdetails.User
  4. We must map numerical roles as SimpleGrantedAuthority objects
  5. We are responsible for interpreting what each numerical role value represents
  6. ROLE_USER and ROLE_ADMIN are abitrary values we assigned to numerical values

Repository Layer

This layer contains a single interface, UserRepository. And this is our data access object (DAO). With the help of Spring Data JPA, Spring will automatically provide the actual implementation.

What is Spring Data JPA?
Spring JPA is part of the umbrella Spring Data project that makes it easy to easily implement JPA based repositories.

Implementing a data access layer of an application has been cumbersome for quite a while. Too much boilerplate code has to be written to execute simple queries as well as perform pagination, and auditing. Spring JPA aims to significantly improve the implementation of data access layers by reducing the effort to the amount that's actually needed. As a developer you write your repository interfaces, including custom finder methods, and Spring will provide the implementation automatically.

Source: http://www.springsource.org/spring-data/jpa



Utility classes

TraceInterceptor class is an AOP-based utility class to help us debug our application. This is a subclass of CustomizableTraceInterceptor (see Spring Data JPA FAQ)



Next

In the next section, we will focus on the configuration files and create them accordingly. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 2) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 1)

In this tutorial, we will create a simple Spring MVC application and secure it with Spring Security 3.1. We have a custom database schema where we will retrieve our authorized users and respective roles. Consequently, we will implement a custom UserDetailsService with the help of Spring Data JPA for quick implementation of JPA based repositories.


Dependencies

  • Spring core 3.1.0.RELEASE
  • Spring Security 3.1.0.RELEASE
  • Spring Data JPA 1.1.0.M1
  • See pom.xml for details

Github

To access the source code, please visit the project's Github repository (click here)

Functional Specs

Before we start, we define our application's specs as follows:
  • Two types of users: admin and regular users
  • A login page that's accessible to all types of users, including unauthorized users
  • All other pages are visible to registered users only
  • A home page
  • A user page
  • An admin page which is visible only to admins

Database

As mentioned earlier, our application relies on a custom database schema to obtain its users.
The database contains two tables: user and role tables.


user and role table design

User table

The user table contains personal information of each user. Notice the password values are hashed using Md5.

user table

Role table

The role table contains role values of each user. We define a role value of 1 as an admin, while a role value of 2 as a regular user.

role table

Screenshots

Before we start the actual development, let's preview how our application should look like by providing screenshots. This is also a good way to clarify further the application's specs.

Login page
The login page contains two input fields: a username and a password field.

Login

Login failure page
When a user fails to login, the login page is displayed again with an error message Login Failure! at the bottom.

Login failure

User's view
When a regular user logs-in, the user should be redirected to the home page with Home, User, and Logout pages accessible to the user.

User's view

Admin's view
When an admin user logs-in, the user should be redirected to the home page with Home, User, Admin, and Logout pages accessible to the user.

Admin's view

Logout success page
When a user successfully logs out, the login page is displayed again with a success message Logout Success! at the bottom.

Logout success

Next

In the next section, we will discuss the project's structure and start writing the Java classes. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 1) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 3)

Review

In the previous section, we have implemented the Java classes and organized them accordingly: domain, repository, service, and controller. In this section, we will create the necessary configuration files, which are mainly XML files, and discuss them thoroughly.


Configuration

There are two important configuration files required to secure our application with Spring Security:
  • spring-security.xml (arbitrary name)
  • web.xml

spring-security.xml

This contains the core Spring Security configuration.


Let's examine further the contents of this file:

the http tag

This means the path /resources should be ignored by Spring Security; therefore it will not be secured. Why do you want to do this? Mainly because these are static images, CSS, and JavaScript files that don't need to be secured.

the second http tag

This contains the core security rules of our application. In previous versions of Spring Security, you're only allowed to have one http element.
  • auto-config is a shorthand for the following (see more):

  • use-expressions allows us to use SPEL (Spring EL expressions) support (see more)

intercept urls

Here we declare URL patterns to be protected. Notice the use of SPEL hasRole and permitAll (see more)

form login

This declares our login settings:
  • login-page: the URL path of our login page
  • authentication-failure-url: the URL where a user will be redirected after a failed login
  • default-target-url: the URL where a user will be redirected after a successful login

denied handler

This declares the URL where a user will be redirected after a denied access.

authentication manager

This is similar with the login element.
  • logout-success-url: the URL where a user will be redirected after a successful logout
  • logout-url: the URL path of our logout page


  • authentication-manager: registers an AuthenticationManager that provides authentication services (see more)
  • authentication-provider: this is a shorthand for configuring a DaoAuthenticationProvider which loads user information from a UserDetailsService (see more)
  • user-service-ref: this allows us to declare a custom UserDetailsService
  • password-encoder: this allows us to declare various password encoders such as md5 and sha (see more)

web.xml

Besides the usual servlet declaration, the web.xml is where you declare the Spring Security filter and name of configuration file to read from.

To enable Spring Security, follow these guidelines:
  • Add a DelegatingFilterProxy
  • Add a springSecurityFilterChain mapping
  • Add a contextConfigLocation You must declare your applicationContext.xml and spring-security.xml here

Here's our complete web.xml file:


Datasource

Since we're using JPA and Spring Data JPA to simplify data access, we must also declare the corresponding configuration files. Please read the inline comments for more info.

spring-data.xml
This contains all datasource-related configuration.


Next

In the next section, we will turn our attention towards the view layer which mainly consists of JSP files. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 3) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 4)

Review

In the previous section, we have created the configuration files and discussed them accordingly. In this section, we will focus on the view layer, in particular the HTML files.


HTML Files

After the configuration files, we'll now move to the HTML files. Actually, we'll be editing JSP files instead.

Login Page

The login page can be designed in any way you like. But there areimportant points to remember. Here they are:
  • Use POST not GET!
  • Use j_spring_security_check for the action value. You may have to modify the action value depending on your URL mapping structure, i.e. it could be ../j_spring_security_check or ../../j_spring_security_check in certain cases.
  • Use j_username for the username input
  • Use j_password for the password input

Here's our complete login.jsp source:


Menu Page

The menu page needs extra configuration because we're required to display all links to admin users but regular users can only see non-admin pages. Particularly, the "Admin" link must be secured.

If you examine carefully the spring-security.xml configuration file, we've already marked the /admin url to be accessible to admins only. But why do we need to secure it again in the menu page? That's because the declaration in spring-security.xml only secures the URL but it doesn't hide the HTML link. To hide and secure the link, we must manually declare it.


User's view


Admin's view

To hide a section of HTML (i.e. a link), follow these steps:
  • Add the following line in the top section of your JSP page (Make sure to edit the role accordingly):
  • Add the following lines to whatever HTML section you need to secure:

Here's our complete menu.jsp source:


Next

In the next section, we will build and run the application using Maven, and show how to import the project in Eclipse. Click here to proceed.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 4) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 5)

Review

We have just completed our application! In the previous sections, we have discussed the functional specs, created the Java classes, declared the configuration files, and wrote the HTMl files. In this section, we will build and run the application using Maven, and show how to import the project in Eclipse.


Running the Application

Access the source code

To download the source code, please visit the project's Github repository (click here)


Preparing the data source

  1. Run MySQL (install one if you don't have one yet)
  2. Create a new database:
    spring_security_tutorial
  3. Import the following file which is included in the source code under the src/main/resources folder:
    spring_security_tutorial.sql

Building with Maven

  1. Ensure Maven is installed
  2. Open a command window (Windows) or a terminal (Linux/Mac)
  3. Run the following command:
    mvn tomcat:run
  4. You should see the following output:
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'tomcat'.
    [INFO] artifact org.codehaus.mojo:tomcat-maven-plugin: checking for updates from central
    [INFO] artifact org.codehaus.mojo:tomcat-maven-plugin: checking for updates from snapshots
    [INFO] ------------------------------------------
    [INFO] Building spring-security Maven Webapp
    [INFO]    task-segment: [tomcat:run]
    [INFO] ------------------------------------------
    [INFO] Preparing tomcat:run
    [INFO] [apt:process {execution: default}]
    [INFO] [resources:resources {execution: default-resources}]
    [INFO] [tomcat:run {execution: default-cli}]
    [INFO] Running war on http://localhost:8080/spring-security-tutorial
    Jan 14, 2012 11:52:54 PM org.apache.catalina.startup.Embedded start
    INFO: Starting tomcat server
    Jan 14, 2012 11:52:54 PM org.apache.catalina.core.StandardEngine start
    INFO: Starting Servlet Engine: Apache Tomcat/6.0.29
    Jan 14, 2012 11:52:54 PM org.apache.catalina.core.ApplicationContext log
    INFO: Initializing Spring root WebApplicationContext
    Jan 14, 2012 11:52:58 PM org.apache.coyote.http11.Http11Protocol init
    INFO: Initializing Coyote HTTP/1.1 on http-8080
    Jan 14, 2012 11:52:58 PM org.apache.coyote.http11.Http11Protocol start
    INFO: Starting Coyote HTTP/1.1 on http-8080
    
  5. Note: If the project will not build due to missing repositories, please enable the repositories section in the pom.xml!

Access the Login page

  1. Follow the steps with Building with Maven
  2. Open a browser
  3. Enter the following URL (8080 is the default port for Tomcat):
    http://localhost:8080/spring-security-tutorial/
  4. Currently there are two accounts included in the sample database. Here are the credentials:
    username password role
    john admin administrator
    jane user regular user

Import the project in Eclipse

  1. Ensure Maven is installed
  2. Open a command window (Windows) or a terminal (Linux/Mac)
  3. Run the following command:
    mvn eclipse:eclipse -Dwtpversion=2.0
  4. You should see the following output:
    [INFO] Scanning for projects...
    [INFO] Searching repository for plugin with prefix: 'eclipse'.
    [INFO] org.apache.maven.plugins: checking for updates from central
    [INFO] org.apache.maven.plugins: checking for updates from snapshots
    [INFO] org.codehaus.mojo: checking for updates from central
    [INFO] org.codehaus.mojo: checking for updates from snapshots
    [INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from central
    [INFO] artifact org.apache.maven.plugins:maven-eclipse-plugin: checking for updates from snapshots
    [INFO] -----------------------------------------
    [INFO] Building spring-security Maven Webapp
    [INFO]    task-segment: [eclipse:eclipse]
    [INFO] -----------------------------------------
    [INFO] Preparing eclipse:eclipse
    [INFO] [apt:process {execution: default}]
    [INFO] [eclipse:eclipse {execution: default-cli}]
    [INFO] Adding support for WTP version 2.0.
    [INFO] -----------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] -----------------------------------------
    
    This command will add the following files to your project:
    .classpath
    .project
    .settings
    target
    You may have to enable "show hidden files" in your file explorer to view them
  5. Open Eclipse and import the project

Conclusion

That's it! We've have successfully completed our Spring Security 3.1 tutorial. We've learned how to secure a Spring MVC application with Spring Security and integrate with a custom user database schema. Furthermore, we have simplified data access with the help of Spring Data JPA.

I hope you've enjoyed this tutorial. Don't forget to check my other tutorials at the Tutorials section.

Revision History


Revision Date Description
1 Jan 13 2012 Uploaded tutorial and Github repository
2 Jan 14 2012 Added revision history
3 Jan 15 2012 Added sample Maven output
4 Jan 19 2012 Added dependencies section
5 Jan 20 2012 Rephrased the logic behind CustomUserDetailsService, Rephrased Part 2
6 Jan 21 2012 Fixed Evgeny Goldin repository location

StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring Security 3.1 - Implement UserDetailsService with Spring Data JPA (Part 5) ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share