Thursday 31 March 2016

JSESSIONID and SoapUI

As the HTTP protocol is stateless, there has always been the question of 'How do we add state?'.

Nowadays this has been "solved" (notice the quotation marks there) by storing the state in the server, and assigning all this state to a "SessionID". The user entering the website gets a newly generated SessionID which is transmitted over and over again, so the server can associate the appropriate State with the appropriate User.

Usually the SessionID is sent along as a cookie, sometimes it is transmitted in the request as a request parameter.

In Java EE and JEE application servers, the cookie is called the "JSESSIONID". You can view an example in the headers shown below.

Retrieve Session id

In the first request a user does for a certain website, there is no cookie yet regarding the session.
PUT /resources/game/Elisa/logon?password=secret HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Fedora; Linux i686; rv:45.0) Gecko/20100101 Firefox/45.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/json; charset=utf-8
X-Requested-With: XMLHttpRequest
Referer: http://localhost:8080/
Cookie: COOKIE_SUPPORT=true; GUEST_LANGUAGE_ID=en_US; LOGIN=6d61617274656e5f6c407961686f6f2e636f6d; REMEMBER_ME=true; SCREEN_NAME=416b713230756641726f6d414441412b304452616b513d3d; _ga=GA1.1.23915379.1454272946
Connection: keep-alive
Content-Length: 0
A new session is created, and a cookie is sent along to the browser of the user with the session id. It is visible in the response below with the name of JSESSIONID.
HTTP/1.1 204 No Content
Server: GlassFish Server Open Source Edition  5.0
X-Powered-By: Servlet/3.1 JSP/2.3  (GlassFish Server Open Source Edition  5.0  Java/Oracle Corporation/1.8)
Set-Cookie: JSESSIONID=29ee5541e005eacdbe4291e5e138; Path=/resources; HttpOnly
Date: Sat, 26 Mar 2016 11:11:11 GMT
From then on the cookie is sent upon each request the browser of the user sends:
GET /resources/private/Elisa/mail?offset=0&_=1459034166678 HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Fedora; Linux i686; rv:45.0) Gecko/20100101 Firefox/45.0
Accept: application/json, text/javascript, */*; q=0.01
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-Requested-With: XMLHttpRequest
Referer: http://localhost:8080/
Cookie: JSESSIONID=536aea5126fb63309b2a7609da51; COOKIE_SUPPORT=true; GUEST_LANGUAGE_ID=en_US; LOGIN=6d61617274656e5f6c407961686f6f2e636f6d; REMEMBER_ME=true; SCREEN_NAME=416b713230756641726f6d414441412b304452616b513d3d; _ga=GA1.1.23915379.1454272946
Connection: keep-alive

HttpOnly

A session id is very vulnerable to man-in-the-middle attack. One slight way to mitigate this is by using the tag "HttpOnly", as shown above.

This means, the cookie is set by the server during a http response, and is read by the server during a http request, and everyone else is not allowed access.

This makes it hard to read the cookie for example using JavaScript/Crosssite scripting.

UML

Perhaps some UML will make things clearer.

SoapUI

Store session id

The idea here is to add a Groovy script as a Test step after the response from the server (with the Set-Cookie). The script retrieves the Session ID from the response headers and stores it in a SoapUI properties cache on testcase, testsuite or project level.
def header = testRunner.testCase.getTestStepByName("logon").httpRequest.response.responseHeaders["Set-Cookie"]
header=header.toString()
start=header.indexOf("JSESSIONID=")
end=header.indexOf("; Path=")
testCaseProperty= header.substring(start,end)
testRunner.testCase.testSuite.setPropertyValue( "JSESSIONID", testCaseProperty )
testRunner.testCase.testSuite.project.setPropertyValue( "JSESSIONID", testCaseProperty )

Use Session id

Now, the idea is to use this stored session id in subsequent http requests in other test steps and even other test cases.

You can define a new header in your subsequent http requests to send the session id along as a cookie, mimicking how a website works:

REST

I will go into REST Services, which are not stateful, in a future blog post. Basically it would mean that we need to send all information required for the REST Service, each and every time we access the REST Service. The state is effectively stored on the client side.

References

QA Strategies Best Testing practices and Automation tips - SOAPUI - Fetch session id from response header
http://qastrategies.blogspot.nl/2012/05/soapui-fetch-session-id-from-response.html
Time is running out, don't lose it. - Set Authentication WebService and Set Authentication Cookies in SoapUi
http://mariemjabloun.blogspot.nl/2014/11/set-webservice-authentication-and-set.html
SoapUI Cookie management
https://siking.wordpress.com/2013/07/25/soapui-cookie-management/
SoapUI - Working with Properties
https://www.soapui.org/functional-testing/properties/working-with-properties.html

1 comment: