Advanced login w dynamic data extraction/correlation

--
-- Dynamic data correlation/extraction example user scenario
--
-- This user scenario code demonstrates how to look for certain data in an HTTP response
-- using regular expression matching. The extracted data can then be used in future requests,
-- typically to simulate CSRF (cross-site request forgery) tokens, session keys or similar
-- dynamic data the server wants included in requests for security or other reasons.
--

-- In this particular example, we load the Load Impact main HTML page, where there is
-- a cross-site request forgery token that we need to extract and include in later requests
-- in order to be able to do many things on the Load Impact site. We then issue a login request
-- without and then with the token, to demonstrate how the login works when the token
-- is present, but not when it isn't.


-- Step 1: First we issue an HTTP request to get some HTML content with the token in it
--
-- Note the use of 'response_body_bytes' to make sure we save the body content
--
log.info('Step 1: Executing GET http://loadimpact.com/')
local response = http.get({ url="http://loadimpact.com/", response_body_bytes=1000000 })


-- Step 2: Using the regex module to find the data we're interested in
--
-- Within the HTML, we want to find a CSRF token that looks like this:
-- CSRF_TOKEN='a14f956c63e19d35c2272d5d1e1a15cff1ba1f01'
-- To find it, we perform a regular expression search in the HTML, looking for "CSRF_TOKEN='x'"
-- where "x" is allowed to be any number of a-z characters or the numbers 0-9
--
local m = regex.match("CSRF_TOKEN='([a-z,0-9]+)'", response.body)


-- Print out some debug information
--
log.info('Step 2: Full string matched by regex: ' .. m:capture(1))
log.info('Step 2: CSRF token was: ' .. m:capture(2))


-- Step 3: Store the extracted string in a local variable for later use
--
local csrf_token = m:capture(2)


-- Step 4-5: build and send a login request.
--
-- We login as user "test@loadimpact.com" with password "test"
--
local login_url = 'https://loadimpact.com/account/signin'
local username = 'test@loadimpact.com'
local password = 'test1234'


-- Step 4: First we build a request that does NOT include the CSRF token, to see what happens
--
local post_data = 'email=' .. url.escape(username) .. '&password=' .. url.escape(password)

-- Then we send it
local response = http.post({
url=login_url,
data=post_data,
response_body_bytes = 1000000
})

-- Print out some debug info
--
log.info('Step 4: First POST returned status code ' .. tostring(response.status_code))
log.info('Step 4: Content-length is ' .. tostring(response.body_size))

-- When logged in at loadimpact.com, you get a "Sign out" link at the top of the page
-- This means we can verify if the login operation worked, by seeing if the returned
-- HTML contains the string "Sign out" or not
--
if string.find(response.body, 'Sign out') == nil then
log.info('Step 4: Login failed on our first attempt')
else
log.info('Step 4: Login succeeded on our first attempt')
end


-- Step 5: Then we build a request that includes the CSRF token
--
local post_data = 'email=' .. url.escape(username) .. '&password=' .. url.escape(password) ..
'&csrf=' .. csrf_token

-- Then we send it
local response = http.post({
url=login_url,
data=post_data,
response_body_bytes = 1000000
})

-- Print out some debug info
--
log.info('Step 5: Second POST returned status code ' .. tostring(response.status_code))
log.info('Step 5: Content-length is ' .. tostring(response.body_size))

-- And check if we are logged on or not
--
if string.find(response.body, 'Sign out') == nil then
log.info('Step 5: Login failed on our second attempt')
else
log.info('Step 5: Login succeeded on our second attempt')
end


Feedback and Knowledge Base