Spring

Navigating Spring Security from thick Client to REST Webservice

When a Web Service is protected by Spring security, and we try to access that Web Service, we are presented with a login page to enter our credentials. After we provide our credentials, this information is stored as part of the session and sent back and forth between the browser and the server in a cookie.

However this is not the way it works with a non-browser, standalone client (like a mobile app) – for obvious reasons.

This note describes a thick client. User requires to login into the thick client. On successful authentication the user’s credentials are stored with the client. When the client accesses the Web Service, the web server responds to the client with the login page. Then the client presents the credentials, and submits it back to the web server.

Thus accessing a Web Service secured by Spring Security is a two-step process.

This note primarily describes the client. Some server-side config files are shown for information.

Follows are relevant code snippets for this scenario.

Comments are provided in bold.

On the Server side

Follows are some standard code snippets to secure a URL pattern with Spring Security with a username and password. Please refer to Spring Security documentation for detailed instructions and samples.

In web.xml

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
   /WEB-INF/mvc-dispatcher-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>Code language: HTML, XML (xml)

In spring-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
 xmlns:beans="http://www.springframework.org/schema/beans" 
 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/security
 http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">


 <!--Web Services with the pattern “/rest/vp/” will be secured -->
 <http auto-config="true">
  <intercept-url pattern="/rest/vp/**" access="ROLE_USER" />
 </http>


 <!—The username and password to be provided isvpUserandvp123-->
 <authentication-manager>
  <authentication-provider>
   <user-service>
    <user name="vpUser" password="vp123" authorities="ROLE_USER" />
   </user-service>
  </authentication-provider>
 </authentication-manager>

</beans:beans>Code language: HTML, XML (xml)

In mvc-dispatcher-servlet.xml

<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.devices.middleware.webservice" />

 <mvc:annotation-driven />

</beans>Code language: HTML, XML (xml)

On the Mobile Client side

// This is the object that we will populate from the JSON object 
                  //returned by the Web Service
   List<AlarmBean> alarmBeanList = new ArrayList<AlarmBean>();
   

   // The username and password authenticated to the client, and required for 
//the Web Service
//String urlParameters=
// "j_username="+userBean.getUsername()+"&j_password="+userBean.getPassword();
String urlParameters="j_username="+”vpUser” +"&j_password="+”vp123”;


     // When Spring Security presents the login page, that page gets submitted to this link. 
  // i.e. - /j_spring_security_check
     String strSpringAuthURL = "http://hostname/j_spring_security_check";
    
     
    
     //This is the REST Web Service to be invoked
     String strWebSvc = "http://hostname/rest/vp/alarm/11";


   try {

     // Create the URL object with the Web Service url
     URL url = new URL(strWebSvc);

      System.out.println("strWebSvc "+strWebSvc);

     // Invoke the URL 
      HttpURLConnection conn = (HttpURLConnection) url
        .openConnection();

      conn.setDoOutput(true);
      conn.setDoInput(true);
      
      conn.setInstanceFollowRedirects(false); 
      // ************* IMP *************
      conn.setRequestMethod("GET"); 
      conn.setRequestProperty("Accept", "application/json");
      conn.setUseCaches (false);




      //HTTP Response codes are
      // 200 is OK
      // 302 is Redirect
      // When the secured Web Service is requested, the web server directs 
  // to the login page and sends a 302 Response code
  
      if (conn.getResponseCode() == 302) {


      System.out.println(" Response code is " + conn.getResponseCode());
     
      String newUrl = conn.getHeaderField("Location");
       
      // Get the cookie. It has the value of the original Web Service URL.
                          //In a browser scenario, after successful authentication, it would’ve 
                          //automatically re-directed to the WS URL
      String cookies = conn.getHeaderField("Set-Cookie");
      
        
      
      //conn = (HttpURLConnection) new URL(strSpringAuthURL + 
  //   ";jsessionid=" + J_SESSION_ID).openConnection();
      conn = (HttpURLConnection) new URL(strSpringAuthURL).openConnection();
                          //Pass on the cookie
      conn.setRequestProperty("Cookie", cookies);
      conn.setDoOutput(true);
      conn.setDoInput(true);
      
      conn.setInstanceFollowRedirects(false); 
      conn.setRequestMethod("POST");
      DataOutputStream wr1 = new DataOutputStream(conn.getOutputStream ());
                          //Pass on the credentials 
      wr1.writeBytes(urlParameters);
      wr1.flush();
      wr1.close();
      
      //System.out.println("Redirect to URL : " + strSpringAuthURL 
  //   + ";jsessionid=" + J_SESSION_ID);
      System.out.println("Redirected to URL : " + strSpringAuthURL );
System.out.println("Response code from Spring Auth URL is " + 
conn.getResponseCode());

      //Get the Web Service URL from the http header
      String strOrigWSUrl = conn.getHeaderField("Location");
      
      String cookies1 = conn.getHeaderField("Set-Cookie");
      
      //conn = (HttpURLConnection) new URL(strOrigWSUrl + 
  //   ";jsessionid=" + J_SESSION_ID).openConnection();

      // Connection is made to the original Web Service URL that we want
      conn = (HttpURLConnection) new URL(strOrigWSUrl).openConnection();

      // ************* IMP *************
      // The cookies that we received after authentication is passed here again.
      conn.setRequestProperty("Cookie", cookies1);
      
      conn.setDoOutput(true);
      conn.setDoInput(true);
      
      conn.setInstanceFollowRedirects(false); 
      conn.setRequestMethod("GET");
      conn.setRequestProperty("Accept", "application/json");
      conn.setUseCaches (false);
      
      
      System.out.println("Redirect to URL strOrigWSUrl : " + strOrigWSUrl);
      // We get a 200 Response code now
      System.out.println(" Response code 555 is " + conn.getResponseCode());
      
      } //end-if for the condition where we checked if the Response code was 302

      //if the response code was not 302 above at the “if” check for the response code, 
                          //and was 200 (assumed, not checked here), 
                          //code would’ve continued here-forward

      // Reading the JSON output returned by the Web Service
      // And populating the AlarmBean object
      BufferedReader br = new BufferedReader(
      new InputStreamReader((conn.getInputStream())));
      String line;
      while ((line = br.readLine()) != null) {
     JSONArray jsa = new JSONArray(line);

     for (int i = 0; i < jsa.length(); i++) {
      JSONObject jo = (JSONObject) jsa.get(i);

      AlarmBean alarmBean = new AlarmBean(jo
        .getInt("alarmId"), jo.getString("timestamp"),
        jo.getString("duration"), jo
          .getString("meterName"), jo
          .getString("alarmType"), jo
          .getString("status"), jo
.getInt("dcId"), jo
.getInt("count"), jo
          .getString("deviceId"), jo
          .getInt("buildingId"), jo
          .getBoolean("disabled"), jo
          .getString("location"), jo
          .getString("dc"), jo
          .getString("buildingName"), jo
          .getInt("acknowledgedBy"), jo
          .getString("ackUserName"), jo
          .getString("acknowledgedOn"), jo
          .getString("thresholdValue"), jo
          .getString("actualValue"));
      alarmBeanList.add(alarmBean);

     }Code language: Java (java)

View Comments

Recent Posts

  • Java

Java URL Encoder/Decoder Example

Java URL Encoder/Decoder Example - In this tutorial we will see how to URL encode/decode…

6 years ago
  • General

How to Show Multiple Examples in OpenAPI Spec

Show Multiple Examples in OpenAPI - OpenAPI (aka Swagger) Specifications has become a defecto standard…

6 years ago
  • General

How to Run Local WordPress using Docker

Local WordPress using Docker - Running a local WordPress development environment is crucial for testing…

6 years ago
  • Java

Create and Validate JWT Token in Java using JJWT

1. JWT Token Overview JSON Web Token (JWT) is an open standard defines a compact…

6 years ago
  • Spring Boot

Spring Boot GraphQL Subscription Realtime API

GraphQL Subscription provides a great way of building real-time API. In this tutorial we will…

6 years ago
  • Spring Boot

Spring Boot DynamoDB Integration Test using Testcontainers

1. Overview Spring Boot Webflux DynamoDB Integration tests - In this tutorial we will see…

6 years ago