Spring MVC Security REST Basic Authentication

STEP 1:- Open Eclipse and Create Dynamic Web Project named SpringSecurityRESTBasicAuthentication

STEP 2:- Make sure you use Target Runtime as Apache Tomcat 7.0.

STEP 3:- copy below jars to WEB-INF/lib folder.
  • aopalliance-1.0.jar
  • aspectjrt-1.8.4.jar
  • commons-io-2.4.jar
  • commons-logging-1.2.jar
  • jackson-annotations-2.6.0.jar
  • jackson-core-2.6.0.jar
  • jackson-databind-2.6.0.jar
  • jtds.jar
  • log4j-1.2.17.jar
  • spring-aop-4.1.4.RELEASE.jar
  • spring-beans-4.1.4.RELEASE.jar
  • spring-context-4.1.4.RELEASE.jar
  • spring-core-4.1.4.RELEASE.jar
  • spring-dao-2.0.8.jar
  • spring-expression-4.1.4.RELEASE.jar
  • spring-jdbc-4.1.4.RELEASE.jar
  • spring-security-config-4.0.2.RELEASE.jar
  • spring-security-core-4.0.2.RELEASE.jar
  • spring-security-oauth2-2.0.8.RELEASE.jar
  • spring-security-taglibs-4.0.2.RELEASE.jar
  • spring-security-web-4.0.2.RELEASE.jar
  • spring-web-4.1.4.RELEASE.jar
  • spring-webmvc-4.1.4.RELEASE.jar
STEP 4:- Create Spring Configuration Bean file. /WebContent/WEB-INF/dispatcher-servlet.xml
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:mvc="http://www.springframework.org/schema/mvc" 
 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.xsd
 http://www.springframework.org/schema/mvc 
 http://www.springframework.org/schema/mvc/spring-mvc.xsd
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context.xsd">
 
 <context:component-scan base-package="com.tutorialsdesk.controllers" />
 <context:component-scan base-package="com.tutorialsdesk.services" />
 
 <mvc:annotation-driven />
 
 <bean id="viewResolver"
 class="org.springframework.web.servlet.view.UrlBasedViewResolver">
 <property name="viewClass"
 value="org.springframework.web.servlet.view.JstlView" />
 <property name="prefix" value="/WEB-INF/views/" />
 <property name="suffix" value=".jsp" />
 </bean>
 
 <bean name="jsonTemplate" class="org.springframework.web.servlet.view.json.MappingJackson2JsonView"/>
</beans>
STEP 5:- Create Spring security configuration file. /WebContent/WEB-INF/spring-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:oauth="http://www.springframework.org/schema/security/oauth2"
 xmlns:security="http://www.springframework.org/schema/security"
 xsi:schemaLocation="http://www.springframework.org/schema/security/oauth2 
 http://www.springframework.org/schema/security/spring-security-oauth2-2.0.xsd
 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.xsd">
 
 
<security:global-method-security pre-post-annotations="enabled"/>

 <security:http use-expressions="true">
 <security:intercept-url access="hasRole('ROLE_VERIFIED')" pattern="/api/**"/>
 <security:intercept-url pattern='/*' access='permitAll'/>

 <security:logout logout-success-url="/"/>

 <security:session-management session-fixation-protection="newSession">
 <security:concurrency-control max-sessions="1"/>
 </security:session-management>

 <security:http-basic />
 </security:http>
 <security:authentication-manager>
 <security:authentication-provider>
 <security:user-service>
 <security:user name="test" password="test" authorities="ROLE_VERIFIED"/>
 </security:user-service>

 </security:authentication-provider>
 </security:authentication-manager>
</beans>

What is relevant here is the <http-basic> element inside the main <http> element of the configuration – this is enough to enable Basic Authentication for the entire application.
The Authentication Manager is not the focus of this tutorial, so we are using an in memory manager with the user and password defined in plaintext.

STEP 6 :- Map Spring configuration files in /WebContent/WEB-INF/web.xml file as below :-
<?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" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
 <display-name>SpringSecurityRESTBasicAuthentication</display-name>
 <servlet>
 <servlet-name>dispatcher</servlet-name>
 <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
 <load-on-startup>1</load-on-startup>
 </servlet>
 <servlet-mapping>
 <servlet-name>dispatcher</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/spring-security.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>
</web-app>

STEP 7 :- Create Controller Class.
  • Package: com.tutorialsdesk.controller
  • Filename: RestController.java
package com.tutorialsdesk.controllers;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.tutorialsdesk.models.Employee;
import com.tutorialsdesk.services.EmployeeService;

@Controller
@RequestMapping()
public class RestController {

 @Autowired
 EmployeeService employeeService;

 @RequestMapping(value = "api/users", method = RequestMethod.GET)
 @ResponseBody
 public List<Employee> list() {
 System.out.println("RestController.list()");
 
 return employeeService.getEmployeesList();
 }
 
}

STEP 9 :- Create Model Class.
  • Package: com.tutorialsdesk.model
  • Filename: Employee.java
package com.tutorialsdesk.models;

import java.io.Serializable;

public class Employee implements Serializable{

 private static final long serialVersionUID = 5088863992478607917L;

 private Integer id;
 
 private String firstName;

 private String lastName;
 
 private String email;

 public Employee(Integer id, String firstName, String lastName, String email) {
 super();
 this.id = id;
 this.firstName = firstName;
 this.lastName = lastName;
 this.email = email;
 }

 public Employee() {
 super();
 }

 public Integer getId() {
 return id;
 }

 public void setId(Integer id) {
 this.id = id;
 }

 public String getFirstName() {
 return firstName;
 }

 public void setFirstName(String firstName) {
 this.firstName = firstName;
 }

 public String getLastName() {
 return lastName;
 }

 public void setLastName(String lastName) {
 this.lastName = lastName;
 }

 public String getEmail() {
 return email;
 }

 public void setEmail(String email) {
 this.email = email;
 }

 public static long getSerialversionuid() {
 return serialVersionUID;
 }

 @Override
 public String toString() {
 return "Employee [id=" + id + ", firstName=" + firstName
 + ", lastName=" + lastName + ", email=" + email + "]";
 }
 
}

STEP 10 :- Create Service Interface and Class.
  • Package: com.tutorialsdesk.services
  • Filename: EmployeeService.java
package com.tutorialsdesk.services;

import java.util.List;

import com.tutorialsdesk.models.Employee;

public interface EmployeeService {
 public List<Employee> getEmployeesList();
}

  • Package: com.tutorialsdesk.services
  • Filename: EmployeeServiceImpl.java
package com.tutorialsdesk.services;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Service;

import com.tutorialsdesk.models.Employee;

@Service
public class EmployeeServiceImpl implements EmployeeService {

 @Override
 public List<Employee> getEmployeesList() {
 List<Employee> employeeList = new ArrayList<Employee>();
 employeeList.add(new Employee(1, "Prince", "Sethi", "prince@gmail.com"));
 employeeList.add(new Employee(2, "Rambir", "Singh", "rambir@gmail.com"));
 employeeList.add(new Employee(3, "Vishnu", "Jangid", "vishnu@gmail.com"));
 return employeeList;
 }

}

STEP 11 :- Create jsp file in /WebContent/WEB-INF folder
  • Filename: index.jsp
<html>
<body>
<h2>Spring REST Security Basic Authentication</h2> 
<a href="http://localhost:8080/SpringSecurityRESTBasicAuthentication/api/users">Get Users List</a>
<br/>
<br/>
Or use CURL command <br/>
<br/>
curl -i --user test:test http://localhost:8080/SpringSecurityRESTBasicAuthentication/api/users

</body>
</html>

STEP 12 :- Run your project enter below URL in your browser

http://localhost:8080/SpringSecurityRESTBasicAuthentication/

STEP 13 :- Consuming The Secured Application The curl command is our go to tool for consuming the secured application.
First, let’s try to request the /api/users without providing any security credentials:
curl -i http://localhost:8080/SpringSecurityRESTBasicAuthentication/api/users

We get back the expected 401 Unauthorized and the Authentication Challenge:
HTTP/1.1 401 Unauthorized
Server: Apache-Coyote/1.1
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Set-Cookie: JSESSIONID=D3E07DD1EE9DA030C14C958CF207D5A2; Path=/SpringSecurityRES
TBasicAuthentication/; HttpOnly
WWW-Authenticate: Basic realm="Spring Security Application"
Content-Type: text/html;charset=utf-8
Content-Language: en
Content-Length: 1061
Date: Fri, 24 Jun 2016 06:17:52 GMT

<html><head><title>Apache Tomcat/7.0.55 - Error report</title><style><!--H1 {fon
t-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:
22px;} H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525
D76;font-size:16px;} H3 {font-family:Tahoma,Arial,sans-serif;color:white;backgro
und-color:#525D76;font-size:14px;} BODY {font-family:Tahoma,Arial,sans-serif;col
or:black;background-color:white;} B {font-family:Tahoma,Arial,sans-serif;color:w
hite;background-color:#525D76;} P {font-family:Tahoma,Arial,sans-serif;backgroun
d:white;color:black;font-size:12px;}A {color : black;}A.name {color : black;}HR
{color : #525D76;}--></style> </head><body><h1>HTTP Status 401 - Full authentica
tion is required to access this resource</h1><HR size="1" noshade="noshade"><p><
b>type</b> Status report</p><p><b>message</b> <u>Full authentication is required
 to access this resource</u></p><p><b>description</b> <u>This request requires H
TTP authentication.</u></p><HR size="1" noshade="noshade"><h3>Apache Tomcat/7.0.
55</h3></body></html>

The browser would interpret this challenge and prompt us for credentials with a simple dialog, but since we’re using curl, this isn’t the case.

Now, let’s request the same resource – /api/users – but provide the credentials to access it as well:
curl -i --user test:test http://localhost:8080/SpringSecurityRESTBasicAuthentication/api/users

Now, the response from the server is 200 OK along with a Cookie:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Set-Cookie: JSESSIONID=299E6E6B73DB9E94E4AAC0AD01F7F258; Path=/SpringSecurityRES
TBasicAuthentication/; HttpOnly
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Fri, 24 Jun 2016 06:19:25 GMT

[{"id":1,"firstName":"Prince","lastName":"Sethi","email":"prince@gmail.com"},{"i
d":2,"firstName":"Rambir","lastName":"Singh","email":"rambir@gmail.com"},{"id":3
,"firstName":"Vishnu","lastName":"Jangid","email":"vishnu@gmail.com"}]

From the browser, the application can be consumed normally – the only difference is that a login page is no longer a hard requirement since all browsers support Basic Authentication and use a dialog to prompt the user for credentials.

STEP 14 :- Further Configuration – The Entry Point By default, the BasicAuthenticationEntryPoint provisioned by Spring Security returns a full html page for a 401 Unauthorized response back to the client. This html representation of the error renders well in a browser, but it not well suited for other scenarios, such as a REST API where a json representation may be preferred. The namespace is flexible enough for this new requirement as well – to address this – the entry point can be overridden:
<security:http-basic entry-point-ref="customAuthenticationEntryPoint" />

The new entry point is defined as a standard bean:
  • Package: com.tutorialsdesk.security
  • Filename: CustomAuthenticationEntryPoint.java
package com.tutorialsdesk.security;

import java.io.IOException;
import java.io.PrintWriter;

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.authentication.www.BasicAuthenticationEntryPoint;
import org.springframework.stereotype.Component;

@Component
public class CustomAuthenticationEntryPoint extends BasicAuthenticationEntryPoint{

 @Override
 public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx) throws IOException, ServletException {
 response.addHeader("WWW-Authenticate", "Basic realm=" + getRealmName() + "");
 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
 PrintWriter writer = response.getWriter();
 writer.println("HTTP Status 401 - " + authEx.getMessage());
 }
 
 @Override
 public void afterPropertiesSet() throws Exception {
 setRealmName("Baeldung");
 super.afterPropertiesSet();
 }
 
}
By writing directly to the HTTP Response we now have full control over the format of the response body. Keep visiting TutorialsDesk for more tutorials and practical programming examples on Spring MVC. Hope we are able to explain you Spring MVC Security REST Basic Authentication Example, if you have any questions or suggestions please write to us using contact us form.

Please share us on social media if you like the tutorial.
SHARE
    Blogger Comment
    Facebook Comment