相信前端开发工程师对CSRF(Cross-site request forgery)跨站请求伪造这个概念都非常熟悉,有的时候也简写成XSRF,是一种对网站的恶意利用。

尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装成受信任用户的请求来利用受信任的网站。

CSRF攻击的防御方式有多种,最简单最易实现的一种思路就是在客户端向服务器发起的请求中放入攻击者无法伪造的信息,并且该信息没有存储于 cookie 之中。技术上来说,当客户端向服务器发起请求执行一些敏感操作之前(比如用HTTP post实现的转账,扣款等功能),服务器端随机产生一个token,返回给客户端。客户端接下来的操作,必须在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”:

--batch_1
Content-Type: multipart/mixed; boundary=changeset_1 --changeset_1
Content-Type: application/http
Content-Transfer-Encoding: binary POST ServiceRequestCollection HTTP/1.1
Content-Length: 5000
Accept: application/json
Content-Type: application/json {
"ServicePriorityCode": "2",
"Name": {"content": "Jerry Testing ticket creation via JMeter ${uuid} "},
"ServiceRequestDescription": [
{
"Text": "Piston Rattling 1 - Generic OData Test Create",
"TypeCode": "10004"
},
{
"Text": "Piston Rattling 2 - Generic OData Test Create",
"TypeCode": "10007"
}
]
}
--changeset_1-- --batch_1--

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构造逻辑上有依赖关系的一系列并发请求的更多相关文章

  1. fleet中service之间的依赖关系

    最近有人在topcoder上提出使用fleet在集群上部署service时有时候会发现,当启动依赖于整个集群服务的service时,只会检查那个service所在机器的依赖关系,这样就会造成一些问题, ...

  2. Spark之RDD依赖关系及DAG逻辑视图

    RDD依赖关系为成两种:窄依赖(Narrow Dependency).宽依赖(Shuffle Dependency).窄依赖表示每个父RDD中的Partition最多被子RDD的一个Partition ...

  3. 如何使用jMeter发送两个逻辑上相关的HTTP请求

    在前一篇文章使用jMeter构造大量并发的随机HTTP请求里我通过jMeter构造了大量的HTTP GET并发请求,对服务器产生了大量读操作. 现在我有另一个需求场景:假设我开发了一个创建Servic ...

  4. 90%的人都不知道的Node.js 依赖关系管理(上)

    转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 原文参考:https://dzone.com/articles/nodejs-dependency-mana ...

  5. Ubuntu上安装gtk2.0不能安装的问题,“下列的软件包有不能满足的依赖关系”

    zez@localhoss:~$ sudo apt-get install libgtk2.0-dev正在读取软件包列表... 完成正在分析软件包的依赖关系树       正在读取状态信息... 完成 ...

  6. 自动配置pom文件,构建maven项目jar包依赖关系,找到jar包运用到jmeter

    首先说下pom文件特别方便的优点: 什么是pom文件? POM(Project Object Model) 是Maven的基础. 它是一个XML文件,包含了Maven用来build项目所需要的项目配置 ...

  7. Ubuntu上安装samba不能安装的问题,“下列的软件包有不能满足的依赖关系”

    前阵子,雨林木风版ubuntu下安装samba的问题,现在写出来分享一下. root@ubuntu:~# apt-get install samba正在读取软件包列表... 完成正在分析软件包的依赖关 ...

  8. ARM开发板上查看动态库或者可执行程序的依赖关系

    以ARM32开发板为例,在/lib下有一个名为ld-linux-armhf.so.3的可执行程序(在ARM64开发板上是/lib/ld-linux-aarch64.so.1),这个程序负责加载可执行程 ...

  9. 类图和对象图教程-类(Class)、接口(Interface)、协作(collaboration)、依赖关系(Dependency)、泛化关系(Generalization)、关联关系(Association)以及实现关系(Realization)

    类图的概念 (转) 一.概述 类图(Class Diagram)是描述类.接口.协作以及它们之间关系的图,用来显示系统中各个类的静态结构.类图是定义其他图的基础,在类图基础上,可以使用状态图.协作图. ...

随机推荐

  1. emacs窗口半透明

    转自 http://blog.csdn.net/dsjlzh/article/details/7804733 ;; transform window;; Anchor: March Liu (刘鑫) ...

  2. LookupError: unknown encoding: cp65001的问题

    在CMD中进入Python2命令行交互模式,输入代码报错: LookupError: unknown encoding: cp65001 解决方法: 在CMD中设置 Python2 的环境变量 PYT ...

  3. Scrum 冲刺博客第二篇

    一.当天站立式会议照片一张 二.每个人的工作 (有work item 的ID),并将其记录在码云项目管理中 昨天已完成的工作 配置和连接微信小程序服务器 个人界面设计 部主页界面设计 答题界面设计 今 ...

  4. 破解b站极验验证码

    这就是极验验证码,通过拖动滑块移动拼图来验证.我们观察到点击滑块时拼图才会出现,所以我们可以在点击滑块之前截取图像,点击滑块再截取一次图像,将前后两次图像做比较就可以找到图片改动的位置.获得位置后,我 ...

  5. bzoj 4540: [Hnoi2016]序列

    Description 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- 1,ar.若1≤l≤s≤t≤r≤n,则称 ...

  6. java 线程池(1)

    问题 : 线程池中的 coreSize 和 maxSize 的作用分别是什么? 未执行的线程池存在在哪种数据类型,为什么使用这种类型的数据结构 ThreadPoolExecutor概述 ThreadP ...

  7. C#在不同平台下DLL的引用问题

    缘起 很多时候,我们需要引用在不同平台下的DLL,32位(X86)和64位(X64).如果平台错误,在C#中会引发BadImageFormatException异常. 解决思路 我们同时不能添加不同平 ...

  8. java设计模式--基础思想总结--抽象类与架构设计思想

    抽象类?这个东西我感觉没什么卵用啊,又不能拿来new对象,没有具体的对象的抽象类,有什么实际的意义呢?这是很多刚刚接触java抽象类语法时的第一反应(当然,包括我).确实,很多刚刚接触抽象类这个概念的 ...

  9. 冒泡排序——Python实现

    一.排序思想 排序思想参见:https://www.cnblogs.com/luomeng/p/10161794.html 二.python实现 def bubble_sort(nums): &quo ...

  10. java温故而知新(8)反射机制

    一.什么是反射机制  简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制  有些时候,我们用过 ...