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>

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 is “vpUser” and “vp123” -->
	<authentication-manager>
		<authentication-provider>
			<user-service>
				<user name="vpUser" password="vp123" authorities="ROLE_USER" />
			</user-service>
		</authentication-provider>
	</authentication-manager>

</beans:beans>

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>

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);

					}

Get our Articles via Email. Enter your email address.

You may also like...

4 Comments

  1. Java freakers says:

    very nice tutorial.
    thanx for sharing.

  2. balkrushn says:

    Very helpful artical…works great…Thanx for the artical.

  3. balkrushn says:

    Do I need to call j_spring_security_check for every webservice request for single user? please give me brief description. Thanx for the help… :)

  4. very nice post ..thanks for this

Leave a Reply

Your email address will not be published. Required fields are marked *