使用jMeter构造逻辑上有依赖关系的一系列并发请求
相信前端開發工程師對CSRF(Cross-site request forgery)跨站請求偽造這個概念都非常熟悉,有的時候也簡寫成XSRF,是一種對網站的惡意利用。
盡管聽起來像跨站腳本(XSS),但它與XSS非常不同,XSS利用站點內的信任用戶,而CSRF則通過偽裝成受信任用戶的請求來利用受信任的網站。
CSRF攻擊的防御方式有多種,最簡單最易實現的一種思路就是在客戶端向服務器發起的請求中放入攻擊者無法偽造的信息,并且該信息沒有存儲于 cookie 之中。技術上來說,當客戶端向服務器發起請求執行一些敏感操作之前(比如用HTTP post實現的轉賬,扣款等功能),服務器端隨機產生一個token,返回給客戶端??蛻舳私酉聛淼牟僮?#xff0c;必須在HTTP請求中以參數的形式把這個服務器端頒發的token帶上。同時服務器端在實現給客戶端分配token的同時,也要加入一個token校驗機制。如果請求中沒有 token 或者 token 內容不正確,則認為可能是 CSRF 攻擊而拒絕該請求。這個token我們一般稱為CSRF token。
講了這么多,是為了引入本文想要討論的話題。假設我想用jMeter測試一個OOdata服務創建Service Ticket的性能。因為創建功能不像讀操作,執行之后會對系統產生持久化影響(Persistence side-effect), 因此服務器端的實現加入了CSRF token的校驗。這就是說,如果我們直接用jMeter構造并發的HTTP post請求,是沒有辦法完成測試的,這些請求因為沒有包含CSRF token,會被服務器端直接拒絕掉。
根據前面描述的CSRF攻防原理,CSRF token是服務器端隨機生成的,客戶端無法用任何技術進行偽造,因為為了測試接口HTTP post操作進行Service Ticket的創建,我們必須構造一個它的前置HTTP GET請求,專門用于得到服務器返回的CSRF token,然后再構造真正用于性能測試的HTTP POST請求,把第一步GET請求獲得的CSRF token附到POST請求的頭部中去。
本文介紹在jMeter里如何維護并配置這種具有依賴關系的一組請求。
當然如果您不喜歡用jMeter,想自己寫代碼實現,也是可以的。可以參考我放在github上的Java代碼實現。
用jMeter的好處是不需要編程,通過簡單的配置就能實現這個性能測試需求,一般沒有開發背景的測試人員也能獨立完成。
First let us have a look how JMeter could archive the same without even one line of programming.
My project in JMeter is displayed with the following hierarchy. I have configured with “Number of 5 threads” in my thread group, so once executed, the response time of these 5 threads are displayed in result table together with average response time.
從下圖能看出,因為拿CSRF token的HTTP GET在邏輯上必須先于實際需要測試性能的HTTP POST請求,這實際上構成了一個Transaction-事務,所以我使用jMeter里提供的Transaction Controller來管理。
Some key points for this JMeter project creation
(1) Since now one thread should cover both XSRF token fetch via HTTP get and Service request creation via HTTP post, so a transaction controller is necessary to include both request.
(2) Create the first HTTP request to fetch XSRF token. The setting could be found below: adding a http header field with name as
x-csrf-token and value as “fetch”:
在HTTP GET請求的頭部加上一個名為x-csrf-token的字段,值賦成fetch。這樣服務器接到這個請求,就知道這是客戶端發起的CSRF token請求,于是服務器響應這個請求,把創建好的隨機CSRF token通過HTTP response頭部字段的方式返回給客戶端。
下一個問題就是,服務器返回給客戶端合法的CSRF token后,jMeter如何讀取到這個token,并用于接下來的請求?
幸運的是,jMeter提供了正則表達式提取式,可以讓我們很方便地從HTTP響應結構中提取出token來。
Create a Regular Expression Extractor to parse the XSRF token from response header and stored it to a variable named “jerrycsrftoken”.
下圖構造了一個jMeter正則表達式提取器,工作于HTTP響應的頭部字段,解析出的token值存儲于變量jerrycsrftoken中。
Before you continue, please make sure that the XSRF token is correctly parsed from request header, which could be confirmed by printing it out in a debug sample:
這個請求構造完之后,我們先試著運行一次,確保在變量jerrycsrftoken里確實看到解析好的CSRF token。
(3) Create another HTTP request with type POST.
這時萬事俱備,我們可以開始構造真正要進行性能測試的HTTP post,即Service Ticket的創建請求了。
請求的報文正文:
Just paste the following text to the tab “Body Data”:
In the body text I use a user-defined variable ${uuid} which we could create it in last step. And for this post request, use the XSRF token fetched from previous HTTP get request.
前面說過,POST請求的頭部需要加上合法的CSRF token,此處我們使用前面GET請求已經拿到的并且存儲于變量jerrycsrftoken中的token值:
我希望最后通過并發測試生成的Service Ticket的描述信息的后綴是1到100的隨機正整數,因此我使用jMeter里自帶的一個隨機數發生器:
(4) As the last step, create a user variable by using JMeter built-in function __Random, to create a random number between 1 ~ 100 as a fragment of created Service Request description.
Now execute the Thread group, and the execution detail for these three HTTP request could be reviewed separately in tree view:
試著運行一下,發現這個POST操作確實按照我們期望的那樣,在HTTP頭部字段里加上了正確合法的CSRF token:
For example, the XSRF token is successfully fetched in the first request: rdPy7zNj_uKDYvQLgfQCFA==
And used as one header field in second HTTP Post request as expected:
And finally in UI we could find the created Service request with random number between 1 ~ 100 as postfix:
在UI上觀測到我構造的5個并發請求創建的Service Ticket,說明CSRF token在服務器端的校驗成功,同時發現描述信息都帶上了隨機數,說明我的jMeter隨機數生成器的用法也正確。
希望本文對大家的工作有所幫助。
要獲取更多Jerry的原創文章,請關注公眾號"汪子熙":
總結
以上是生活随笔為你收集整理的使用jMeter构造逻辑上有依赖关系的一系列并发请求的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: lol霸天剑魔炫彩怎么买(艾欧尼亚VS诺
- 下一篇: iPhone 不是拍照第一,但为什么摄影