Let's get down to business

In this section, we will develop an application using Spring MVC, Hibernate, and Spring Security. Here, we have a custom login page, logout page, employee page (to list employees), and add employee page (to add employees), which is secured by the Spring Framework. A user can log into the application using the custom login page and view the secured page based on the authentication and authorization. A user will be redirected to the custom login page on any authentication failure along with the error message, which describes the reason for failure. User will be logged out from the application on clicking on the logout link and redirected to the logout page.

Project structure

The overall project structure is as follows:

Project structure

In the pom.xml file, you'll find the following code:

A list of all required dependencies are listed here in pom.xml. To get Spring Security features, you need to add spring-security-core, spring-security-web, and spring-security-config to the pom.xml file:

<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>org.packt.Spring.chapter8.springsecurity</groupId>
   <artifactId>ehrPayrollWithSecurity</artifactId>
   <packaging>war</packaging>
   <version>0.0.1-SNAPSHOT</version>
   <name>ehrPayrollWithSecurity Maven Webapp</name>
   <url>http://maven.apache.org</url>

Here, the properties specify the versions used:

   <properties>
          <spring.version>4.1.3.RELEASE</spring.version>
          <security.version>4.0.0.CI-SNAPSHOT</security.version>
          <hibernate.version>4.2.11.Final</hibernate.version>
          <org.aspectj-version>1.7.4</org.aspectj-version>
   </properties>

Here are the dependencies for all the JARs:

<dependencies>
   <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
   </dependency>
   <!-- Spring  -->
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-core</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 transaction -->
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
   </dependency>
   <!-- Spring Security -->
   <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-core</artifactId>
      <version>${security.version}</version>
   </dependency>
   <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
      <version>${security.version}</version>
   </dependency>
   <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <version>${security.version}</version>
   </dependency>
   <!-- Spring ORM -->
   <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${spring.version}</version>
   </dependency>
   <!-- AspectJ -->
   <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>${org.aspectj-version}</version>
   </dependency>
   <!-- Hibernate ORM framework dependencies -->
   <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>${hibernate.version}</version>
   </dependency>
   <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-entitymanager</artifactId>
      <version>${hibernate.version}</version>
   </dependency>
   <!-- Java Servlet and JSP dependencies (for compilation only) -->
   <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
   </dependency>
   <dependency>
      <groupId>javax.servlet.jsp</groupId>
      <artifactId>jsp-api</artifactId>
      <version>2.1</version>
      <scope>provided</scope>
   </dependency>
   <!-- JSTL dependency -->
   <dependency>
      <groupId>jstl</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
   </dependency>
   <!-- Apache Commons DBCP dependency (for database connection pooling) -->
   <dependency>
      <groupId>commons-dbcp</groupId>
      <artifactId>commons-dbcp</artifactId>
      <version>1.4</version>
   </dependency>
   <!-- postgresql Connector Java dependency (JDBC driver for postgresql) -->
   <dependency>
      <groupId>postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <version>9.0-801.jdbc4</version>
   </dependency>
   <!-- logging -->
   <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.4.2</version>
   </dependency>
   <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.14</version>
   </dependency>
</dependencies>
<build>
   <finalName>ehrPayrollWithSecurity</finalName>
</build>
</project>

Adding filters to web.xml

Add filters to web.xml, where all incoming requests will be handled by Spring Security. The Spring Security JAR contains DelegatingFilterProxy, which delegates control to a filter chaining in the Spring Security internals. The bean name should be springSecurityFilterChain.

In the web.xml file, you'll find the following code:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns="http://java.sun.com/xml/ns/javaee" 
   xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" 
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
   http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" 
   id="WebApp_ID" version="3.0">
   <display-name>Archetype Created Web Application</display-name>
   <servlet>
      <servlet-name>SpringDispatcher</servlet-name>
      <servlet-class>
         org.springframework.web.servlet.DispatcherServlet
      </servlet-class>
      <load-on-startup>1</load-on-startup>
   </servlet>
   <servlet-mapping>
      <servlet-name>SpringDispatcher</servlet-name>
      <url-pattern>/</url-pattern>
   </servlet-mapping>
   <listener>
      <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
   <context-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>  
         /WEB-INF/SpringDispatcher-servlet.xml,
         /WEB-INF/spring-security.xml  
      </param-value>
   </context-param>
   <!-- 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>
</web-app>

Resolving your view

To resolve the view, view resolver has been added to the SpringDispatcher-servlet.xml configuration file. Also, dataSource, sessionFactory, and transactionManager have been defined here:

<?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:aop="http://www.springframework.org/schema/aop"
   xmlns:context="http://www.springframework.org/schema/context"
   xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
   http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
   http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
   http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd">
   <context:component-scan base-package="org.packt.Spring.chapter8.springsecurity" />
   <context:property-placeholder location="/WEB-INF/hibernate.properties" />
   <bean id="dataSource"

class="org.springframework.jdbc.datasource.DriverManagerDataSource">
      <property name="driverClassName" value="${jdbc.driverClassName}" />
      <property name="url" value="${jdbc.url}" />
      <property name="username" value="${jdbc.username}" />
      <property name="password" value="${jdbc.password}" />
   </bean>
   <bean id="sessionFactory"
      class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
      <property name="dataSource" ref="dataSource" />
      <property name="annotatedClasses"
         value="org.packt.Spring.chapter8.springsecurity.model.Employee" />
      <property name="hibernateProperties">
         <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
         </props>
      </property>
   </bean>
   <bean id="transactionManager"
      class="org.springframework.orm.hibernate4.HibernateTransactionManager">
      <property name="sessionFactory" ref="sessionFactory" />
   </bean>
   <tx:annotation-driven transaction-manager="transactionManager" />
   <bean
      class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <property name="prefix">
         <value>/WEB-INF/views/</value>
      </property>
      <property name="suffix">
         <value>.jsp</value>
      </property>
   </bean>
</beans>

Let's add a custom login

We have defined a role called ROLE_ADMIN. We have defined credentials for this role. Also, we have mapped URLs with roles that will be handled by Spring Security. To provide custom login form, add <form:login> in this file. When the user tries to access a secured resource, a custom login page will be served.

In the security-config.xml file, you'll find the following code:

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/security"
   xsi:schemaLocation="http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/security 
   http://www.springframework.org/schema/security/spring-security-3.1.xsd">
   <http auto-config="true">
      <intercept-url pattern="/employee/*" access="ROLE_ADMIN" />
      <form-login login-processing-url="/login" login-page="/loginPage"
         username-parameter="username" password-parameter="password"
         default-target-url="/employee/listemployee"
         authentication-failure-url="/loginPage?auth=fail" />
      <logout logout-url="/logout" logout-success-url="/logoutPage" />
   </http>
   <authentication-manager>
      <authentication-provider>
         <user-service>
            <user name="ravi" password="ravi@123" authorities="ROLE_ADMIN" />
         </user-service>
      </authentication-provider>
   </authentication-manager>
</beans:beans>

Mapping your login requests

The LoginController class contains two methods, namely logoutPage and loginPage, with request mapping. The /loginPage redirects the user to the login page and the /logoutpage redirects the user to the logout page:

package org.packt.Spring.chapter8.springsecurity.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class LoginController {

   @RequestMapping(value = "/logoutPage", method = RequestMethod.GET)
    public String logoutPage() {
        return "logout";
    }
     
    @RequestMapping(value = "/loginPage", method = RequestMethod.GET)
    public String loginPage() {
        return "login";
    }
}

Obtaining the employee list

This controller class has the listEmployee(), addEmployee(), and deleteEmployee() methods. In the EmployeeController.java file, you'll find the following code:

package org.packt.Spring.chapter8.springsecurity.controller;

import org.packt.Spring.chapter8.springsecurity.model.Employee;
import org.packt.Spring.chapter8.springsecurity.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
@RequestMapping("/employee")
public class EmployeeController {

   @Autowired
   private EmployeeService employeeService;

   @RequestMapping(value = "/listemployee", method = RequestMethod.GET)
   public String listEmployees(ModelMap model) {
          model.addAttribute("employeesList", employeeService.listEmployee());
          return "employee";
   }

   @RequestMapping(value = "/addemployee", method = RequestMethod.GET)
   public ModelAndView addEmployee(ModelMap model) {
          return new ModelAndView("addemployee", "command", new Employee());
   }

   @RequestMapping(value = "/updatemployee", method = RequestMethod.POST)
   public String updateEmployee(
               @ModelAttribute("employeeForm") Employee employee, ModelMap model) {
          this.employeeService.insertEmployee(employee);
          model.addAttribute("employeesList", employeeService.listEmployee());
          return "employee";
   }

   @RequestMapping(value = "/delete/{empId}", method = RequestMethod.GET)
   public String deleteEmployee(@PathVariable("empId") Integer empId,
                ModelMap model) {
         this.employeeService.deleteEmployee(empId);
         model.addAttribute("employeesList", employeeService.listEmployee());
         return "employee";
   }
}

Let's see some credentials

This login page provides an input box to accept credentials from the user. In the login.jsp file, you'll find the following code:

<%@ taglib uri='http://java.sun.com/jsp/jstl/core' prefix='c'%>
<html>
<head>
<title>Login Page</title>
</head>
<body>
    <h2 style="color: orange">Login to eHR Payroll</h2>
    <c:if test="${'fail' eq param.auth}">
        <div style="color:red">
                Login Failed!!!<br />
                Reason : ${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
         </div>
    </c:if>
    <form action="${pageContext.request.contextPath}/login" method="post">
        <table frame="box" cellpadding="0" cellspacing="6">
            <tr>
                <td>Username:</td>
                <td><input type='text' name='username' /></td>
            </tr>
            <tr>
                <td>Password:</td>
                <td><input type='password' name='password'></td>
            </tr>
            <tr>
                <td colspan='2'><input name="submit" type="submit" value="Submit"></td>
            </tr>
        </table>
    </form>
</body>
</html>

Time to log out

This logout page reflects that the user has been logged out from the application. In the logout.jsp file, you'll find the following code:

<html>
<title>Logout Page</title>
<body>
    <h2>You have been successfully logged out.</h2>
    <a href="${pageContext.request.contextPath}/employee/listemployee">Login to eHR Payroll</a>
</body>
</html>

Running the application

Once you deploy the web application after starting the server, open the URL http://localhost:8080/ehrPayrollWithSecurity/loginPage a custom login page will appear:

Running the application

If you enter the wrong credentials, the following error will appear:

Running the application

If you enter the correct credentials, you will be navigated to the listEmployee page:

Running the application

Clicking on Logout will navigate you to the logout page, as shown here:

Running the application
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.47.203