security

Spring Security with Spring REST Web-service

Photo of Chandan SinghChandan SinghApril 22nd, 2016Last Updated: September 5th, 2017
2 241 4 minutes read

In one of the previous example, we have studied about exposing a simple REST web-service usingSpring REST and also how toconsume a REST web-service.

In this example, we will go a step further and attempt to access a REST Web-Service which is secured by Spring Security. We shall use Spring-REST to host the REST Web-Service. So let’s start with the project set-up:

1. Project Set-Up

We shall use Maven to setup our project. Open Eclipse and create a simple Maven project and check the skip archetype selection checkbox on the dialogue box that appears. Replace the content of the existingpom.xml with the one provided below:

pom.xml

<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>com.jcg.examples.springSecuritywithRest</groupId><artifactId>SpringSecurityWithRest</artifactId><packaging>war</packaging><version>0.0.1-SNAPSHOT</version><name>SpringSecurityWithRest Maven Webapp</name><url>http://maven.apache.org</url><dependencies><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>3.8.1</version><scope>test</scope></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>4.2.3.RELEASE</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-core</artifactId><version>4.0.3.RELEASE</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-web</artifactId><version>4.0.3.RELEASE</version></dependency><dependency><groupId>org.springframework.security</groupId><artifactId>spring-security-config</artifactId><version>4.0.3.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>4.2.3.RELEASE</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-web</artifactId><version>4.2.3.RELEASE</version></dependency></dependencies><build><finalName>SpringSecurityWithRest</finalName><pluginManagement><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></pluginManagement></build></project>

This will import the required JAR dependencies in the project. We can now start with the actual Spring-Security implementation for the REST Web-Service.

2. Implementation

We have already demonstrated how we can configureSpring Security for a Web-application. For Spring Security to work with REST Wev-Service we will make some changes to thesecurity-config.xml as under :

security-config.xml

<?xml version="1.0" encoding="UTF-8"?><beans:beans xmlns="http://www.springframework.org/schema/security"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"xmlns:sec="http://www.springframework.org/schema/security"xmlns:context="http://www.springframework.org/schema/context"xsi:schemaLocation="      http://www.springframework.org/schema/security      http://www.springframework.org/schema/security/spring-security-4.0.xsd      http://www.springframework.org/schema/beans      http://www.springframework.org/schema/beans/spring-beans-4.0.xsd      http://www.springframework.org/schema/context  http://www.springframework.org/schema/context/spring-context-4.0.xsd"><sec:http entry-point-ref="customEntryPoint" use-expressions="true"><sec:custom-filter ref="authenticationFilter"before="PRE_AUTH_FILTER" /><sec:intercept-url pattern="/**"access="hasAuthority('AUTH_USER')" /><sec:logout delete-cookies="JSESSIONID" /><sec:csrf disabled="true" /></sec:http><context:component-scan base-package="com.jcg.examples" /><sec:authentication-manager alias="authenticationManager"><authentication-provider ref="customAuthenticationProvider" /></sec:authentication-manager><context:component-scan base-package="com.jcg.examples" /><beans:beanclass="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"><beans:property name="authenticationManager" ref="authenticationManager" /><beans:property name="postOnly" value="false" /><beans:property name="authenticationSuccessHandler" ref="customSuccessHandler" /></beans:bean><beans:beanclass="com.jcg.examples.authentication.CustomSuccessHandler" /></beans:beans>

The configuration starts by establishing an entry point for the all incoming request. All the requests for the application go through thisentry-point and hence this is the point where user-authentication occurs. In a traditional web-application this is point is created by default when we use thesec:http auto-config="true" in thesecurity-config.xml configuration(refer the above link). To create a custom entry-point, we need to provide aentry-point-ref bean in thehttp tag. We will look at its implementation later in the example.

Next, important piece of configuration here is the configuration ofAuthentication Filter. Since we cannot haveform based authentication filter here, we need to provide our own authentication strategy. This authentication filter will use theauthentication manager to authenticate the user. If the user is successfully authenticated the user is allowed to access the resource he/she is requesting. In case of a authentication-failure, the user receives aresponse header with401 error-code.

We need to implement a successful-authentication handler. The reason is, in default spring security case the user isredirected to the resource he has requested and when we try to this in a web-service we get a 301 code, which means the resource has been moved permanently instead of a200 OKresponse from the server. So, we implementsuccess-handler which simply over-rides this default behavior.

The rest of the configuration remains similar as in the case of a Spring-Security with normal Web-Application.

Now, let us have a look at the implementation of different components we have discussed above :

CustomEntryPoint.java

package com.jcg.examples.authentication;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.security.core.AuthenticationException;import org.springframework.security.web.AuthenticationEntryPoint;import org.springframework.stereotype.Component;@Componentpublic class CustomEntryPoint implements AuthenticationEntryPoint{@Overridepublic void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException{System.out.println("Entering commence due to failed Authentication"); response.sendError( HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized Access!" );}}

To create a customEntry-point into our application we just need to implement theorg.springframework.security.web.AuthenticationEntryPoint interface and over-ride its commence method. This method is invoked in the event of a failed authentication. We have marked this as a component so that we need not explicitly define the bean in the xml file.

CustomSuccessHandler.java

package com.jcg.examples.authentication;import java.io.IOException;import javax.servlet.ServletException;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.springframework.security.core.Authentication;import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;public class CustomSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler{@Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException{System.out.println("authentication successful!");}}

CustomSuccessHandler simply overrides the default action of theonAuthenticationSuccess method ofSavedRequestAwareAuthenticationSuccessHandler class so that the request does not get redirected.

Spring Security usesJ2EE Filter to implement security. So we need to configure the same in theweb.xml

web.xml

<web-app 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_3_0.xsd"version="3.0"><display-name>Spring REST Security Example</display-name><context-param><param-name>contextConfigLocation</param-name><param-value>classpath:/security-config.xml</param-value></context-param><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><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener><servlet><servlet-name>Spring-Controller</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:/spring-beans.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet><servlet-mapping><servlet-name>Spring-Controller</servlet-name><url-pattern>/</url-pattern></servlet-mapping><session-config><session-timeout>15</session-timeout></session-config></web-app>

That is all about configuring the Spring Security. Let’s have a look at a basicREST Controller and thespring-beans.xml

CustomController.java

package com.jcg.examples.controller;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;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.bind.annotation.RestController;@RestControllerpublic class CustomController{@RequestMapping(value="/welcome/{customer}",method=RequestMethod.POST)public ResponseEntity<String> welcomeUser(@PathVariable("customer") String customer){System.out.println("Inside welcomeUser in controller");return new ResponseEntity<String>("Welcome "+customer,HttpStatus.OK);}@RequestMapping(value = "/login", method = RequestMethod.POST)    public String login() {System.out.println("Welcome called Login");        return "welcome";    }}

spring-beans.xml

<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"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"><context:component-scan base-package="com.jcg.examples" /></beans>

That is all from the implementation point of view for the Spring Security with REST. Now, let’s test out the configuration!

curl -i -X POST -d username=Chandan -d password=Chandan -c C:\Users\cshambhunathsingh\Desktop\temp\cookies.txt  http://localhost:8080/SpringSecurityWithRest/login

Fig 1 : REST login
Fig 1 : REST login

This creates a new cookie file at the path passed in the argument. This cookie contains theJSessionId. ThisJSessionId gets invalidated after 15 minutes of inactivity as mentioned in thesession-timeout tag of theweb.xml

Accessing a resource after successful authentication :

curl -i -X POST -b  C:\Users\cshambhunathsingh\Desktop\temp\cookies.txt http://localhost:8080/SpringSecurityWithRest/welcome/Chandan

Fig 2 : Successful REST Consumption
Fig 2 : Successful REST Consumption

Now, I delete the cookie file and try to access the protected the resource again. We should see the401 error message

curl -i -X POST -b  C:\Users\cshambhunathsingh\Desktop\temp\cookies.txt http://localhost:8080/SpringSecurityWithRest/welcome/Chandan

Fig 3 : UnAuthorised Login-401 Error
Fig 3 : UnAuthorised Login-401 Error

3. Download The Source Code

This was an example of how we can secure our REST Web-Service using Spring Security Module.

Download
You can download the source code of this example here:SpringSecurityWithRest.zip
Do you want to know how to develop your skillset to become aJava Rockstar?
Subscribe to our newsletter to start Rockingright now!
To get you started we give you our best selling eBooks forFREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to theTerms andPrivacy Policy

Thank you!

We will contact you soon.

Photo of Chandan SinghChandan SinghApril 22nd, 2016Last Updated: September 5th, 2017
2 241 4 minutes read
Photo of Chandan Singh

Chandan Singh

Chandan holds a degree in Computer Engineering and is a passionate software programmer. He has good experience in Java/J2EE Web-Application development for Banking and E-Commerce Domains.

Related Articles

Subscribe
Notify of
guest
I agree to theTerms andPrivacy Policy
The comment form collects your name, email and content to allow us keep track of the comments placed on the website. Please read and accept our website Terms and Privacy Policy to post a comment.

I agree to theTerms andPrivacy Policy
The comment form collects your name, email and content to allow us keep track of the comments placed on the website. Please read and accept our website Terms and Privacy Policy to post a comment.