我的服务器在HTML响应中嵌入CSRF令牌。客户端将运行JavaScript,它将提取令牌并将其发送回服务器。
但是Load Impact无法在客户端执行JS。
如何使用LoadImpact处理CSRF?
答案 0 :(得分:2)
您需要做的是在用户场景脚本中执行与客户端Javascript相同的操作,以存储和重用服务器发送的CSRF令牌。
下面是一个代码示例,带有注释。此示例代码对于查看是否需要在负载测试中执行任何类型的动态数据提取/关联也很有用。 (请注意,该示例适用于Load Impact V2,但今天不起作用,因为我们不再使用CSRF令牌)。
--
-- 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