First Time Spring Security

Authentication “Who are you?” & Authorization “What can you do?” can be managed using Spring Security. Here we will see a simple example of using Spring Security to authenticate and/or authorize a user to access Spring MVC controller.

springsource

Objectives:

  • Get introduced to Spring Security?
  • How to authenticate and/or authorize a user?

Environment & Tools:

  • Eclipse
  • Maven
  • Jetty
  • Browser (FireFox, Chrome, or other)

Libraries:

  • Spring Framework (3.1.x)
  • Spring Security (3.1.x)

( 1 ) Project Structure

spring-security-1

( 2 ) Spring MVC Web App

We will start by building a Spring MVC application without Spring security.

  • RestController.java
  • hello.jsp
  • rest-servlet.xml
  • web.xml
  • /src/main/java/com/hmkcode/controllers/RestController.java

This controller has two methods.

  • any() will be called by URL: /rest/controller/any
  • user() will be called by URL: /rest/controller/user
  • The message of these two methods will be viewed in hello.jsp page.
package com.hmkcode.controllers;

import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
@RequestMapping("/controller")
public class RestController {

	public RestController(){
		System.out.println("init RestController");
	}

	// URL: /rest/controller/any
	 @RequestMapping(value="/any", method = RequestMethod.GET)
	 public String any(ModelMap model) {

			model.addAttribute("message", "This URL can be accessed by any one");
			return "hello";

	}

	 // URL: /rest/controller/user
	@RequestMapping(value="/user", method = RequestMethod.GET)
	 public String user(ModelMap model) {
		String user = SecurityContextHolder.getContext().getAuthentication().getName();

		model.addAttribute("message", "This URL can be accessed only by authorized user "+user);

		return "hello"; 
	}

}
  • /src/main/webapp/hello.jsp

The output of the controller will be redirected and view in this page.

<html>
<body>
	<h1>Message : ${message}</h1>	
</body>
</html>
  • /src/main/webapp/WEB-INF/rest-servlet.xml

Here we scan passed package for all controllers and define the jsp view resolver.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc" 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/context


http://www.springframework.org/schema/context/spring-context-3.0.xsd


http://www.springframework.org/schema/mvc


http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

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

	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	  <property name="prefix">
		<value>/</value>
	  </property>
	  <property name="suffix">
		<value>.jsp</value>
	  </property>
	</bean>
</beans>
  • /src/main/webapp/WEB-INF/web.xml
<?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_3_0.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>SPRING MVC SECURITY</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>

  	<!-- Spring MVC -->
	<servlet>
  		<servlet-name>rest</servlet-name>  	           
  		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  	</servlet>
  	<servlet-mapping>
  		<servlet-name>rest</servlet-name>
  		<url-pattern>/rest/*</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/rest-servlet.xml
		</param-value>
	</context-param>

</web-app>

( 3 ) Adding Spring Security

  • spring-security.xml
  • web.xml “add new lines”
  • /src/main/webapp/WEB-INF/spring-security.xml

We will create a new file to configure Spring security. In this file we define what roles are needed to access a specific URL. And we hard-code two users (name “hmkcode” & “user2″ , passwords and authorities “roles”).

<?xml version="1.0" encoding="UTF-8"?>
<bean:beans xmlns:bean="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-3.1.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="/rest/controller/any/**" access="ROLE_ANONYMOUS,ROLE_USER"/>
		<intercept-url pattern="/rest/controller/user/**" access="ROLE_USER" />
	</http>

	<authentication-manager>
	  <authentication-provider>
	    <user-service>
			<user name="hmkcode" password="1234" authorities="ROLE_USER" />
			<user name="user2" password="1234" authorities="ROLE_ANONYMOUS" />
	    </user-service>
	  </authentication-provider>
	</authentication-manager>

</bean:beans>
  • /src/main/webapp/WEB-INF/web.xml

We revisit web.xml to add “spring-scurity.xml” to contextConfigLocation parameter and to define spring security filter “DelegatingFilterProxy”

<?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_3_0.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>SPRING MVC SECURITY</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  
  	<!-- Spring MVC -->
	<servlet>
  		<servlet-name>rest</servlet-name>  	           
  		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  	</servlet>
  	<servlet-mapping>
  		<servlet-name>rest</servlet-name>
  		<url-pattern>/rest/*</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/rest-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>

( 4 ) Run

Try to access /rest/controller/any, you will see the following

Try to access /rest/controller/user, you will be redirected to this login page.

Note: this login page is auto generated by Spring .

Now, if you login with “hmkcode” you see the following page

If you login with “user2″ you will get access denied.

Source Code @ GitHub