spring

Spring Security Quick Start Tutorial

In this Spring Security Quick Start post I show you how to use Spring Security framework to secure Spring MVC web application. I will demo simple protect on web application it will force users must login with appropriate user before can access specific page. I also demo how to customize login page and access denied page.

To begin this tutorial you need follow tools and techniques:

  • Eclipse
  • JDK 7
  • Spring MVC 4.0.4
  • Spring security 3.2.3
  • Maven 3
  • Bootstrap 3

1. Spring security quick start project structure

Below is structure of this Spring Security Quick Start project

spring-security-project-structure

2. Dependencies

We need following dependencies for Spring MVC

<dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${org.springframework-version}</version>
      <exclusions>
        <!-- Exclude Commons Logging in favor of SLF4j -->
        <exclusion>
          <groupId>commons-logging</groupId>
          <artifactId>commons-logging</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${org.springframework-version}</version>
    </dependency>

We exclude commons-logging cause we want to use slf4j with log4j for loggin in our application.

To use Spring Security we need add follow dependencies

<dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-web</artifactId>
      <version>3.2.3.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-config</artifactId>
      <version>3.2.3.RELEASE</version>
    </dependency>

3. Spring MVC Web application

In this sample i build two controllers. I use LoginController to show login page.

package com.devjav.spring;

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

/**
 * 
 * @author Pham Thai Thinh
 * 
 */
@Controller
public class LoginController {
  @RequestMapping(value = {"/login.do","/"}, method = RequestMethod.GET)
  public String showLogin() {
    return "login";
  }

}

**Note: If We not provide login page Spring Security will generate it for us. But in this post i want to custom my login page so i write controller to do that work.

The second controller is HomePageController, this process and mapping for three URL

  • /home.do: for user home page that will show after user with ROLE_USER login
  • /admin/home.do: this for admin user home page
  • /accessdenined.do: this URL will show for any url access with unpropriate role.
package com.devjav.spring;

import java.util.Locale;

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

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {

  private static final Logger logger = LoggerFactory.getLogger(HomeController.class);

  /**
   * Simply selects the home view to render by returning its name.
   */
  @RequestMapping(value = "/home.do", method = RequestMethod.GET)
  public String home(Locale locale) {
    logger.info("Welcome User home! The client locale is {}.", locale);

    return "home";
  }
  @RequestMapping(value = "/admin/home.do", method = RequestMethod.GET)
  public String Adminhome(Locale locale) {
    logger.info("Welcome to Admin home! The client locale is {}.", locale);

    return "adminhome";
  }
  @RequestMapping(value = "/accessdenied.do", method = RequestMethod.GET)
  public String accessDenied() {
    logger.info("Access deniend.");
    return "accessdenied";
  }
}

The web pages using this tutorial

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
<title>Login</title>
<link rel="stylesheet"
  href='<spring:url value="/resources/css/bootstrap.min.css"/>' />
<link rel="stylesheet"
  href='<spring:url value="/resources/css/custom.css"/>' />
</head>
<body>
  <div id="login-form">
    <spring:url value="/dologin.do" var="url" />
    <form:form role="form" action="${url }" method="POST">
      <legend>Sign in</legend>
      <c:if test="${param.error != null}">
        <div class="alert alert-danger">
          Failed to login.
          <c:if test="${SPRING_SECURITY_LAST_EXCEPTION != null}">
              Reason: <c:out
              value="${SPRING_SECURITY_LAST_EXCEPTION.message}" />
          </c:if>
        </div>
      </c:if>
      <div class="form-group">
        <label for="username">Username</label> <input type="text"
          id="username" class="form-control" required="required" name="username"
          placeholder="Enter username">
      </div>
      <div class="form-group">
        <label for="password">Password</label> <input id="c"
          type="password" class="form-control" required="required" name="password"
          placeholder="Password">
      </div>
      <button type="submit" class="btn btn-default">Login</button>
    </form:form>
  </div>
</body>
</html>

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
  <title>Home</title>
  <link rel="stylesheet"
  href='<spring:url value="/resources/css/bootstrap.min.css"/>' />
  <link rel="stylesheet"
  href='<spring:url value="/resources/css/custom.css"/>' />
</head>
<body>
 <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">DEVJAV</a>
        </div>
        <div class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
            <li class="active"><a href="#">Home</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </div>

    <div class="container">

      <div class="starter-template">
        <h1>User View</h1>
        <p class="lead">This is user home page</p>
      </div>

    </div><!-- /.container -->
</body>
</html>

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
  <title>Home</title>
  <link rel="stylesheet"
  href='<spring:url value="/resources/css/bootstrap.min.css"/>' />
  <link rel="stylesheet"
  href='<spring:url value="/resources/css/custom.css"/>' />
</head>
<body>
 <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">DEVJAV</a>
        </div>
        <div class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
            <li class="active"><a href="#">Home</a></li>
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </div>

    <div class="container">

      <div class="starter-template">
        <h1>Admin View</h1>
        <p class="lead">This is Admin home page</p>
      </div>

    </div><!-- /.container -->
</body>
</html>

 

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page session="false" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Access denied</title>
<link rel="stylesheet"
  href='<spring:url value="/resources/css/bootstrap.min.css"/>' />
<link rel="stylesheet"
  href='<spring:url value="/resources/css/custom.css"/>' />
</head>
<body>
<div id="error-area">
<h2>Access Denined</h2>
<p class="alert">You don't have permission to access this page.</p>
</div>
</body>
</html>

 

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

  <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->

  <!-- Enables the Spring MVC @Controller programming model -->
  <annotation-driven />

  <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
  <resources mapping="/resources/**" location="/resources/" />
  <beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
  </beans:bean>

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

</beans:beans>

4. Spring Security

Create a Spring security configuration file security.xml

<?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:security="http://www.springframework.org/schema/security"
  xsi:schemaLocation="http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
  <security:http pattern="/resources/**" security="none" />
  <security:http auto-config="true" use-expressions="true">
    <security:intercept-url pattern="/" access="permitAll" />
    <security:intercept-url pattern="/login.do" access="permitAll" />
    <security:intercept-url pattern="/accessdenied.do" access="permitAll" />
    <security:intercept-url pattern="/home.do" access="hasRole('ROLE_USER')" />
    <security:intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')" />
    <security:form-login login-page="/login.do" login-processing-url="/dologin.do"
      username-parameter="username" password-parameter="password"
      authentication-failure-url="/login.do?error=true" default-target-url="/home.do"
      always-use-default-target="true" />
    <security:access-denied-handler error-page="/accessdenied.do"/>
  </security:http>
  <security:authentication-manager>
    <security:authentication-provider>
      <security:user-service>
        <security:user name="devjav" password="devjav" authorities="ROLE_USER" />
        <security:user name="admin" password="devjav" authorities="ROLE_ADMIN" />
      </security:user-service>
    </security:authentication-provider>
  </security:authentication-manager>
</beans>

We customise login form so we must define follow security:form-login tag

  • login-page : to config what url will use to show login page
  • login-processing-url: to config custom url as login entry point instead default j_spring_security_check
  • username-parameter: parameter on login form contain user name to login
  • password-parameter: parameter on login form contain password to login
  • authentication-failure-url: url will be call if authentication failure
  • default-target-url: default url will be redirect to when login success
  • always-use-default-target: set to true if you want every login will bring to default-target-url, if set to false it will bring you to the page that force you login when access.

To customise access denied page when user access with unappropriate role or permission we set parameter and define control handler for this config security:access-denied-handler

In this post i just using memory credetials define for authenticate so i define following lines. In other posts i will help you more on customise Spring Security.

<security:authentication-manager>
    <security:authentication-provider>
      <security:user-service>
        <security:user name="devjav" password="devjav" authorities="ROLE_USER" />
        <security:user name="admin" password="devjav" authorities="ROLE_ADMIN" />
      </security:user-service>
    </security:authentication-provider>
  </security:authentication-manager>

As above i define two users devjav with role ROLE_USER and admin with role ROLE_ADMIN. ROLE_USER can access /home.do url and ROLE_ADMIN can access URLs /admin/**

 5. Web.xml configuration

To integration spring security we must define filter with exactly name springSecurityFilterChain

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" 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">

  <!-- The definition of the Root Spring Container shared by all Servlets 
    and Filters -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml,/WEB-INF/spring/security.xml</param-value>
  </context-param>

  <!-- Creates the Spring Container shared by all Servlets and Filters -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <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>
  <!-- Processes application requests -->
  <servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>

6. Demo
Run application and we try to access http://localhost:8080/spring/home.do Spring Security will force you to login page cause you did not login yet.
login-page

Login with wrong credential you will see error as below

login-wrongLogin with wright credential devjav/devjav it will take you to home page

login-success
Now to demo access denied, you must go to http://localhost:8080/spring/login.do and login with credential admin/devjav It will take you to http://localhost:8080/spring/home.do but you don’t have right on this url so it will bring to accessdenied page.

access-denied
6. Source code
You can download complete source code on this link

2 thoughts on “Spring Security Quick Start Tutorial”

  1. Pingback: Java Dev world

Leave a Reply