Jmeter接口测试

目录

为什么需要接口测试

接口测试流程

Jmeter介绍

Jmeter组件

 Jmeter的目录结构

三类接口

http协议

Jmeter使用

1、用户注册接口

 2、Jmeter接口关联

1、cookie,session,token的区别

2、域和跨域请求

3、token实现

正则表达式

Json提取器

文件上传

 cookie

 断言

响应断言

 JSON断言

 csv文件添加参数

Jmeter直连数据库

 Jmeter生成报告

Jmeter使用ant插件生成报告

数据加密

加密方式的分类

DES/AES加密

Base64加密

RSA加密

 MD5(不可逆)

 接口签名


为什么需要接口测试

1、现在的很多项目都是采用前后端分离的形式,那么前后端的完成度有时是不同步的。我们可以在前端代码没出来之前,对已经出来的接口进行接口测试,这样可以将测试提前,及早的发现bug

2、如果等到前端界面出来之后,结合后端代码一起进行功能测试,这时前端页面就可能已经做了对数据的校验,这时错误数据是没办法传递给后端的。但是,绕过前端是很容易的,后端接口也应该对数据进行核验,防止出现bug,所以需要对接口进行测试

接口测试流程

1、拿到接口测试文档,分析接口参数(传参方式,地址,端口,数据发送格式,响应结果,响应状态码等)
2、根据接口测试文档编写测试数据
3、使用接口测试工具进行测试
4、输出测试报告

Jmeter介绍

Jmeter是根据java研发出来的接口测试工具,同时也可以执行性能测试

Jmeter组件

1、测试计划:Jmeter测试的起点
2、线程组:线程的集合
3、配置元件:配置请求
4、前置处理器:请求之前的操作
5、定时器:延迟请求
6、逻辑控制器:处理请求逻辑
7、取样器:发送请求的最小单元
8、后置处理器:请求之后的操作
9、断言:判断请求结果是否正常
10、监听器:收集测试结果

 Jmeter的目录结构



bin目录下的 jmeter.bat文件:Jmeter的启动文件

三类接口

1、基于http协议的接口,通过json传输数据
2、通过webservice协议的接口,通过xml传输数据
3、基于dubbo协议的接口,通过json传输数据

主要使用的是http协议

http协议

HTTP协议(超文本传输协议)是一种网络通信协议,它允许将超文本标记语言(HTML)文档从Web服务器传送到客户端的浏览器。默认端口:80

http协议包括请求和响应两部分

响应状态码由三位数字组成,第一个数字定义了响应的类别,且有五种类型

1xx:指示信息--表示请求已接收,继续处理
2xx:成功--表示请求已被成功接收、理解、接受
3xx:重定向--要完成请求必须进行更进一步的操作
4xx:客户端错误--请求有语法错误或请求无法实现
5xx:服务器端错误--服务器未能实现合法的请求

常用的有 200:请求成功,301:永久重定向 302:临时重定向 404:资源找不到 405:请求方法错误 500:服务器错误

Jmeter使用

1、用户注册接口

注册接口分析:
1、协议:http协议
2、服务器:localhost
3、端口:8080
4、路径:send/register
5、请求格式:application/json
6、方法:post

 7、完整url:http://127.0.0.1:8080/send/register


 1、在http请求默认值中设置采取协议《配置文件中》

https协议默认端口443,http协议默认端口80

设置默认请求路径:http://127.0.0.1:8080

 2、设置请求头:数据格式为json《配置文件中》

 3、发送请求(取样器-》http请求)

选中post请求,设置路径,请求数据

http://127.0.0.1:8080内容会根据HTTP请求默认设置来填充

 4、设置结果树,运行查看结果(监听器-》查看结果树)

状态码被设置为201

 当请求数据是{
    "name":"123",
    "password":"1234567"
},响应是"注册成功",状态码200

 

 2、Jmeter接口关联

1、cookie,session,token的区别

1、为什么出现cookie,session,token:

http协议是无状态连接的。比如说用户登陆成功了,但是你查找登录信息的时候显示并没有登录,因为登录接口和获取登录信息的接口之间是没有任何关系的,这时候为了让接口之间产生关系,就产生了cookie

2、什么是cookie:cookie是存储在浏览器上的一段数据。在用户登录成功之后,登录接口的响应头中产生了一个set-cookie字段,浏览器获取到了响应,将set-cookie字段的值保留在了客户端,下一次申请访问登录状态查询接口的时候,请求头中就会自动带上这个cookie值,服务器就可以根据这个cookie值,知道是哪一个客户端在请求,就可以判断用户是否登录

3、什么是session:session中文意思是会话,也就是说浏览器一旦和服务器开始了通信,就会建立一个通道(会话),在这个通道里,浏览器和服务器可以进行数据交互。session是存储在服务器中的,因为每一个客户端都会和浏览器建立一个通道,为了保证一个通道只给指定的客户端通信,就需要设置一个唯一id(session_id),客户端每次请求时,带上这个session_id,就可以找到这个唯一的通道。

在用户登录成功之后,登录接口的响应头中产生了一个set-cookie字段,set-cookie字段中存储的数据是session_id,浏览器获取到了响应,将set-cookie字段的值以cookie的形式保留在了客户端,下一次申请访问登录状态查询接口的时候,请求头中就会自动带上这个cookie值,服务器就可以根据这个cookie值,知道是哪一个客户端在请求

4、什么是token:token是身份牌。当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。

5、三者的优势和劣势

1、cookie:存储在服务器中的数据,不会占用到服务器资源,但是可以被人为删除或者被窃取,也不会支持跨域访问

2、session:以id的形式标识一个会话,客户端可以在会话有效期内,长时间的和浏览器保证通信。但是如果用户长时间不和浏览器通信,就会造成浏览器内存的浪费;随着并发量增大,服务器资源就会有很大的消耗;sessionid是存储在cookie中的,也不能进行跨域访问;如果存在多个服务器,会话存储在a服务器上,a服务器挂了,那么这个会话也就不存在了,b,c服务器是不能感知到这个会话的

3、session是http协议规定的,token是开发定义的。token可以存在于hearder/url/body中,也即是说,客户端只需要在请求时传递这个token值,而不是一定要存在于cookie中,token也就可以支持跨域请求。服务端无需存储token ,只需要验证token信息是否正确即可,而session需要在服务端存储,一般是通过cookie中的sessionID在服务端查找对应的session

2、域和跨域请求

域由三部分组成:协议,主机名,端口,只要这三个中有一个不同,那么就是不同的域

比如http://127.0.0.0:8080和https://127.0.0.0:8080就是不同的域。

跨域请求就是在一个域中,获取另外一个域中的资源

但是跨域请求是有危害的:

比如存在a和b两个网站,这两个网站是不同的域。浏览器向a网站发送登录请求,服务器设置登录凭证,浏览器得到响应就会创建cookie存储这个登录凭证。不存在跨域请求限制时,b网站嵌入的脚本可以获取到a网站的登录信息,从而可以使用用户的登录信息进行操作。

同源策略:阻止访问不同源的资源,来防止跨域攻击,也就是不允许跨域访问

3、token实现

token(令牌,访问资源的凭证) 认证是一种机制,具体的实现可以是一个随机的字符串

可以在用户登录后,将token值存储数据库,响应头中设置token,然后下一次请求在请求头中传入token值

1、服务器生成token


@Controller
@RequestMapping("/send")
public class Login {
    @Autowired
    LoginMapper loginMapper;
    @ResponseBody
    @RequestMapping("/login")
    public User login(String name, String password) {
        if (name.equals("123") && password.equals("123")) {
            String id = String.valueOf(UUID.randomUUID());//生成一个几乎不可能生成的字符串
            if (loginMapper.add(id, name, password) == 1){
                User user=new User();
                user.setId(id);
                return user;
            }
        }
        return null;
    }
}

2、在前端中 如何传递token

前端中设置localStorage,设置的变量属于全局变量,作用域是整个客户端,也就是在一个页面设置localStorage,在另外一个页面也可以获取到这个变量

localStorage.setItem(key,value):设置localStorage变量

在页面发送请求时,设置请求头:header:key(key可以根据localStorage变量获取),服务器从请求头中获取这个信息


@Controller
@RequestMapping("/send")
public class Login {
    @Autowired
    LoginMapper loginMapper;
    @ResponseBody
    @RequestMapping("/login")
    public String login(String name, String password) {
        if (name.equals("123") && password.equals("123")) {
            String id = String.valueOf(UUID.randomUUID());//生成一个几乎不可能生成的字符串
            if (loginMapper.add(id, name, password) == 1)
                return id;
        }
        return null;
    }
}

 向数据库存储数据,并可以看到返回的token值

 在界面请求时,在请求头存储token值

@Controller
@RequestMapping("/get")
public class CheckLoginState {
    @Autowired
    SelectTokenMapper selectTokenMapper;

    @ResponseBody
    @RequestMapping("/check")
    public String get(HttpServletRequest request) {
        String httpHandler = request.getHeader("token");//获取token数据
        //这里从数据库中查找token
        if (selectTokenMapper.get(httpHandler) != null)
            return "用户已经登录";
        return "用户没有登录";
    }

}
create table token(
    id varchar(100),
    name varchar(10),
    password varchar(20)
)

在实际应用中,也要存储时间,来设置token的有效期

在检测登录状态时(要求检测登录成功),用户需要先登录,这时接口之间就存在关联关系,也就是检测接口要获取登录接口的token

Jmeter处理接口关联,有两种方式:正则表达式 和 json提取器

正则表达式

1、在登录接口之后添加后置处理器(选中正则表达式提取器),用于请求之后的数据操作

 

 缺省值:如果没有获取到数据,会使用默认值

在调试取样器的结果树中可以看到这个值

 2、在检测登录请求的请求头设置token

 3、运行观察结果

Json提取器

 

 在json语法中,使用$表示全局,.表示引用 ,$.id就可以获取id值

1、在登录请求后设置后置处理器,选中Json提取器

 同样,在调试取样器可以获取到结果

2、在检测状态请求之前,设置请求头

 3、运行,检测结果

文件上传


@Controller
@RequestMapping("/send")
public class upload {
    @PostMapping("/upload")
    public void Upload(@RequestParam("file") MultipartFile file, HttpServletResponse response) throws IOException {
        String name = file.getOriginalFilename();
        System.out.println(name);
        response.setStatus(200);
        File newfile = new File("C:\\Users\\30283\\Desktop\\novel\\photo\\" ,name);
        file.transferTo(newfile);
    }
}

url:http://localhost:8080/send/upload

请求方式:post

参数:文件

请求格式:

Content-Type

multipart/form-data

如果上传文件的路径中包括中文,会出现乱码问题

 解决方式:

1、

 2、apache-jmeter-5.1.1上传附件含中文时乱码问题解决 - 简书

 文件上传成功

 cookie

1、当第一次获取到cookie时,HttpCookie管理器会自动保留cookie值

2、在第二次到第n次请求服务器时,HttpCookie管理器会自动将cookie值存入到Http请求body中

 setcookie的响应头中,包含生成的cookie,内部存储sessionId

getcookie的请求头中,包含setcookie的cookie

 断言

用于判断结果是否和预取结果一致

响应断言

 模式匹配规则中:

1、包括和匹配,支持了正则表达式

2、相等和字符串不支持正则表达式

3、包括和字符串是语义一致的,匹配和相等是语义一致的,只要支不支持正则的区别

4、否:如果表达式结果为真,断言结果为假,表达式结果为假,断言结果为真

5、或者:存在多个断言,只要一个断言为真,结果为真

比如:1、断言响应状态为200

 2、断言请求头包括JSESSIONID

 JSON断言

断言返回数据的state字段的值为0

 csv文件添加参数

@Controller
@RequestMapping("/send")
public class Login {

    @ResponseBody
    @RequestMapping("/login")
    public State login(String name, String password) {
        if ("123".equals(name)&&"123".equals(password)) {
            State state = new State();
            state.setState(100);
            return state;
        }
        State state = new State();
        state.setState(101);
        return state;
    }
}

1、创建csv文件,内部包含测试数据

 2、添加csv配置文件设置(配置文件中)

3、设置http请求的传入参数值

 4、在登录请求外面设置循环控制器,用于循环发送请求

 5、设置断言

根据返回值设置断言(断言返回值和csv文件的state的值相等)

 6、运行结果

 发送了3次请求,且都断言成功

Jmeter直连数据库

让jmeter直接和数据库连接,从而检测数据库数据和响应得到的数据是否匹配

1、在配置文件中添加jdbc配置  《JDBC Connection Configuration

1.1给数据库连接池设置变量名称

1.2 设置数据库连接

  1. 设置url: jdbc:mysql://127.0.0.1:3306/novel?useSSL=false&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull&useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC

  1.  设置驱动包
  2. 设置账号
  3. 设置密码

 2、在测试计划页面中导入mysql驱动包

 3、设置jdbc请求

 检测结果:执行了查询语句

 

 Jmeter生成报告

 会在生成目录里,包含html文件

 这个index.html文件就是生成的图像化报告

但是这个图形化报告不包括具体的请求四要素和响应四要素,看到的信息有限

Jmeter使用ant插件生成报告

1、下载ant文件,配置环境

 2、将ant的bin目录配置到path环境变量

 3、配置ant的编译文件build.xml

新建的txt文件,并将此文件改名为build.xml

文件内容

修改如下配置

<?xml version="1.0" encoding="UTF-8"?>
<project name="ant-jmeter-test" default="run" basedir=".">
<property environment="env"/>
<tstamp>
        <format property="time" pattern="yyyy_MM_dd_hh_mm" />
    </tstamp>
    <!-- 需要调用的jmeter目录,根据需要进行修改,本次使用的linux路径-->  
    <property name="jmeter.home" value="E:\apache-jmeter-5.2.1" />
    <property name="report.title" value="接口自动化测试"/>
    <!-- jmeter生成jtl格式的结果报告的路径--> 
    <property name="jmeter.result.jtl.dir" value="E:\ants\jtl" />
    <!-- jmeter生成html格式的结果报告的路径-->
    <property name="jmeter.result.html.dir" value="E:\ants\html" />
	<property name="jmeter.result.html.dir1" value="report" />
    <!-- 生成的报告的前缀-->  
    <property name="ReportName" value="接口自动化汇总报告_" />
	<property name="ReportName1" value="接口自动化详细报告_" />
    <property name="jmeter.result.jtlName" value="${jmeter.result.jtl.dir}/${ReportName}${time}.jtl" />
    <property name="jmeter.result.htmlName" value="${jmeter.result.html.dir}/${ReportName}${time}.html" />
    <property name="jmeter.result.htmlName1" value="${jmeter.result.html.dir1}/${ReportName1}${time}.html" />
    <target name="run">
	   <!--antcall target="delete" /-->
        <antcall target="test" />
        <antcall target="report" />
    </target>
	
    <!-- 该命令用来删除今天已经执行过的jtl,防止旧数据重叠
	<target name ="delete">
		<delete file="${jmeter.result.jtl.dir}/${ReportName}${env.BUILD_ID}.jtl"/>
	</target>
	-->  
	
	<!-- 该命令为执行命令-->  
    <target name="test">
        <taskdef name="jmeter" classname="org.programmerplanet.ant.taskdefs.jmeter.JMeterTask" />
        <jmeter jmeterhome="${jmeter.home}" resultlog="${jmeter.result.jtlName}">
            <!-- 声明要运行的脚本路径"*.jmx"指包含此目录下的所有jmeter脚本-->
            <testplans dir="E:\ants" includes="*.jmx" />
            <property name="jmeter.save.saveservice.output_format" value="xml"/>
        </jmeter>
    </target>

    <path id="xslt.classpath">
        <fileset dir="${jmeter.home}/lib" includes="xalan*.jar"/>
        <fileset dir="${jmeter.home}/lib" includes="serializer*.jar"/>
    </path>
  <!-- 该命令为生成汇总和详细报告  -->  
    <target name="report">
        <tstamp> <format property="report.datestamp" pattern="yyyy/MM/dd HH:mm" /></tstamp>
        <xslt 
              classpathref="xslt.classpath"
              force="true"
              in="${jmeter.result.jtlName}"
              out="${jmeter.result.htmlName}"
              style="${jmeter.home}/extras/jmeter-results-report_21.xsl">
              <param name="dateReport" expression="${report.datestamp}"/>
       </xslt>
	   <xslt 
              classpathref="xslt.classpath"  
              force="true"
              in="${jmeter.result.jtlName}"
              out="${jmeter.result.htmlName1}"
              style="${jmeter.home}/extras/jmeter.results.shanhe.me.xsl">
              <param name="dateReport" expression="${report.datestamp}"/>
       </xslt>
	 

                <!-- 因为上面生成报告的时候,不会将相关的图片也一起拷贝至目标目录,所以,需要手动拷贝 --> 
        <copy todir="${jmeter.result.html.dir}">
            <fileset dir="${jmeter.home}/extras">
                <include name="collapse.png" />
                <include name="expand.png" />
            </fileset>
        </copy>
		<!-- 【详细报告】拷贝图片到目标目录-->
		<copy todir="${jmeter.result.html.dir1}">
            <fileset dir="${jmeter.home}/extras">
                <include name="collapse.png" />
                <include name="expand.png" />
            </fileset>
        </copy>
    </target>
</project>

3、修改jmeter配置文件

修改Jmeter的bin目录下jmeter.properties文件的配置:jmeter.save.saveservice.output_format=xml

这一步操作使Jmeter报告输出文件格式为xml

4、执行

 进入到build.xml文件所在的路径 执行ant命令

1、运行ant报错taskdefclassorg.programmerplanet.ant.taskdefs.jmeter.JMeterTaskcannotbefound

原因:配置时,ant-lib文件中缺少ant-jmeter-1.1.1.jar导致,只需将Jmeter-extras中的ant-jmeter-1.1.1.jar复制到ant-lib文件中即可

2、报错: stylesheet C:\Users\30283\Desktop\apache-jmeter-5.4.1\extras\jmeter.results.shanhe.me.xsl doesn't exist.

手动下载该文件(网络搜索下载),命名成jmeter.results.shanhe.me.xsl,然后放置在apache-jmeter-5.4.1\extras文件夹下

文件内容如下

<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
 
<!--
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at
 
       http://www.apache.org/licenses/LICENSE-2.0
 
   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
-->
 
<!-- 
    Stylesheet for processing 2.1 output format test result files 
    To uses this directly in a browser, add the following to the JTL file as line 2:
    <?xml-stylesheet type="text/xsl" href="../extras/jmeter-results-detail-report_21.xsl"?>
    and you can then view the JTL in a browser
-->
 
<xsl:output method="html" indent="yes" encoding="UTF-8" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN" />
 
<!-- Defined parameters (overrideable) -->
<xsl:param    name="showData" select="'y'"/>
<xsl:param    name="titleReport" select="'Load Test Results'"/>
<xsl:param    name="dateReport" select="'date not defined'"/>
 
<xsl:template match="testResults">
    <html>
        <head>
            <title><xsl:value-of select="$titleReport" /></title>
            <style type="text/css">
                body {
                    font:normal 68% verdana,arial,helvetica;
                    color:#000000;
                }
                table tr td, table tr th {
                    font-size: 68%;
                }
                table.details tr th{
                    color: #ffffff;
                    font-weight: bold;
                    text-align:center;
                    background:#2674a6;
                    white-space: nowrap;
                }
                table.details tr td{
                    background:#eeeee0;
                    white-space: nowrap;
                }
                h1 {
                    margin: 0px 0px 5px; font: 165% verdana,arial,helvetica
                }
                h2 {
                    margin-top: 1em; margin-bottom: 0.5em; font: bold 125% verdana,arial,helvetica
                }
                h3 {
                    margin-bottom: 0.5em; font: bold 115% verdana,arial,helvetica
                }
                .Failure {
                    font-weight:bold; color:red;
                }
                
    
                img
                {
                  border-width: 0px;
                }
                
                .expand_link
                {
                   position=absolute;
                   right: 0px;
                   width: 27px;
                   top: 1px;
                   height: 27px;
                }
                
                .page_details
                {
                   display: none;
                }
                                
                                .page_details_expanded
                                {
                                    display: block;
                                    display/* hide this definition from  IE5/6 */: table-row;
                                }
 
 
            </style>
            <script language="JavaScript"><![CDATA[
                           function expand(details_id)
               {
                  
                  document.getElementById(details_id).className = "page_details_expanded";
               }
               
               function collapse(details_id)
               {
                  
                  document.getElementById(details_id).className = "page_details";
               }
               
               function change(details_id)
               {
                  if(document.getElementById(details_id+"_image").src.match("expand"))
                  {
                     document.getElementById(details_id+"_image").src = "collapse.png";
                     expand(details_id);
                  }
                  else
                  {
                     document.getElementById(details_id+"_image").src = "expand.png";
                     collapse(details_id);
                  } 
                           }
            ]]></script>
        </head>
        <body>
        
            <xsl:call-template name="pageHeader" />
            
            <xsl:call-template name="summary" />
            <hr size="1" width="95%" align="center" />
            
            <xsl:call-template name="pagelist" />
            <hr size="1" width="95%" align="center" />
            
            <xsl:call-template name="detail" />
            
               <xsl:call-template name="myStyle" />
 
        </body>
    </html>
</xsl:template>
 
<xsl:template name="pageHeader">
    <h1><xsl:value-of select="$titleReport" /></h1>
    <table width="100%">
        <tr>
            <td align="left">Date report: <xsl:value-of select="$dateReport" /></td>
            <td align="right">Designed for use with <a href="http://jmeter.apache.org/">JMeter</a> and <a href="http://ant.apache.org">Ant</a>.</td>
        </tr>
    </table>
    <hr size="1" />
</xsl:template>
 
<xsl:template name="summary">
    <h2>Summary</h2>
    <table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
        <tr valign="top">
            <th># Samples</th>
            <th>Failures</th>
            <th>Success Rate</th>
            <th>Average Time</th>
            <th>Min Time</th>
            <th>Max Time</th>
        </tr>
        <tr valign="top">
            <xsl:variable name="allCount" select="count(/testResults/*)" />
            <xsl:variable name="allFailureCount" select="count(/testResults/*[attribute::s='false'])" />
            <xsl:variable name="allSuccessCount" select="count(/testResults/*[attribute::s='true'])" />
            <xsl:variable name="allSuccessPercent" select="$allSuccessCount div $allCount" />
            <xsl:variable name="allTotalTime" select="sum(/testResults/*/@t)" />
            <xsl:variable name="allAverageTime" select="$allTotalTime div $allCount" />
            <xsl:variable name="allMinTime">
                <xsl:call-template name="min">
                    <xsl:with-param name="nodes" select="/testResults/*/@t" />
                </xsl:call-template>
            </xsl:variable>
            <xsl:variable name="allMaxTime">
                <xsl:call-template name="max">
                    <xsl:with-param name="nodes" select="/testResults/*/@t" />
                </xsl:call-template>
            </xsl:variable>
            <xsl:attribute name="class">
                <xsl:choose>
                    <xsl:when test="$allFailureCount &gt; 0">Failure</xsl:when>
                </xsl:choose>
            </xsl:attribute>
            <td align="center">
                <xsl:value-of select="$allCount" />
            </td>
            <td align="center">
                <xsl:value-of select="$allFailureCount" />
            </td>
            <td align="center">
                <xsl:call-template name="display-percent">
                    <xsl:with-param name="value" select="$allSuccessPercent" />
                </xsl:call-template>
            </td>
            <td align="center">
                <xsl:call-template name="display-time">
                    <xsl:with-param name="value" select="$allAverageTime" />
                </xsl:call-template>
            </td>
            <td align="center">
                <xsl:call-template name="display-time">
                    <xsl:with-param name="value" select="$allMinTime" />
                </xsl:call-template>
            </td>
            <td align="center">
                <xsl:call-template name="display-time">
                    <xsl:with-param name="value" select="$allMaxTime" />
                </xsl:call-template>
            </td>
        </tr>
    </table>
</xsl:template>
 
<xsl:template name="pagelist">
    <h2>Pages</h2>
    <table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
        <tr valign="top">
            <th>URL</th>
            <th># Samples</th>
            <th>Failures</th>
            <th>Success Rate</th>
            <th>Average Time</th>
            <th>Min Time</th>
            <th>Max Time</th>
            <th></th>
        </tr>
        <xsl:for-each select="/testResults/*[not(@lb = preceding::*/@lb)]">
            <xsl:variable name="label" select="@lb" />
            <xsl:variable name="count" select="count(../*[@lb = current()/@lb])" />
            <xsl:variable name="failureCount" select="count(../*[@lb = current()/@lb][attribute::s='false'])" />
            <xsl:variable name="successCount" select="count(../*[@lb = current()/@lb][attribute::s='true'])" />
            <xsl:variable name="successPercent" select="$successCount div $count" />
            <xsl:variable name="totalTime" select="sum(../*[@lb = current()/@lb]/@t)" />
            <xsl:variable name="averageTime" select="$totalTime div $count" />
            <xsl:variable name="minTime">
                <xsl:call-template name="min">
                    <xsl:with-param name="nodes" select="../*[@lb = current()/@lb]/@t" />
                </xsl:call-template>
            </xsl:variable>
            <xsl:variable name="maxTime">
                <xsl:call-template name="max">
                    <xsl:with-param name="nodes" select="../*[@lb = current()/@lb]/@t" />
                </xsl:call-template>
            </xsl:variable>
            <tr valign="top">
                <xsl:attribute name="class">
                    <xsl:choose>
                        <xsl:when test="$failureCount &gt; 0">Failure</xsl:when>
                    </xsl:choose>
                </xsl:attribute>
                <td>
                <xsl:if test="$failureCount > 0">
                  <a><xsl:attribute name="href">#<xsl:value-of select="$label" /></xsl:attribute>
                  <xsl:value-of select="$label" />
                  </a>
                </xsl:if>
                <xsl:if test="0 >= $failureCount">
                  <xsl:value-of select="$label" />
                </xsl:if>
                </td>
                <td align="center">
                    <xsl:value-of select="$count" />
                </td>
                <td align="center">
                    <xsl:value-of select="$failureCount" />
                </td>
                <td align="right">
                    <xsl:call-template name="display-percent">
                        <xsl:with-param name="value" select="$successPercent" />
                    </xsl:call-template>
                </td>
                <td align="right">
                    <xsl:call-template name="display-time">
                        <xsl:with-param name="value" select="$averageTime" />
                    </xsl:call-template>
                </td>
                <td align="right">
                    <xsl:call-template name="display-time">
                        <xsl:with-param name="value" select="$minTime" />
                    </xsl:call-template>
                </td>
                <td align="right">
            
                          <xsl:call-template name="display-time">
                        <xsl:with-param name="value" select="$maxTime" />
                    </xsl:call-template>
                    
                </td>
                <td align="center">
                   <a href="">
                      <xsl:attribute name="href"><xsl:text/>javascript:change('page_details_<xsl:value-of select="position()" />')</xsl:attribute>
                      <img src="expand.png" alt="expand/collapse"><xsl:attribute name="id"><xsl:text/>page_details_<xsl:value-of select="position()" />_image</xsl:attribute></img>                      
                   </a>
                </td>
            </tr>
            
                        <tr class="page_details">
                           <xsl:attribute name="id"><xsl:text/>page_details_<xsl:value-of select="position()" /></xsl:attribute>
                           <td colspan="8" bgcolor="#FF0000">
                              <div align="center">
                     <b>Details for Page "<xsl:value-of select="$label" />"</b>
                     <table bordercolor="#000000" bgcolor="#2674A6" border="0"  cellpadding="1" cellspacing="1" width="95%">
                     <tr>
                        <th>Thread</th>
                        <th>Iteration</th>
                        <th>Time (milliseconds)</th>
                        <th>Bytes</th>
                        <th>Success</th>
                     </tr>
                                      
                     <xsl:for-each select="../*[@lb = $label and @tn != $label]">                                             
                        <tr>
                           <td><xsl:value-of select="@tn" /></td>
                           <td align="center"><xsl:value-of select="position()" /></td>
                           <td align="right"><xsl:value-of select="@t" /></td>
                           <!--  TODO allow for missing bytes field -->
                           <td align="right"><xsl:value-of select="@by" /></td>
                           <td align="center"><xsl:value-of select="@s" /></td>
                        </tr>
                     </xsl:for-each>
                     
                     </table>
                  </div>
                           </td>
                        </tr>
            
        </xsl:for-each>
    </table>
</xsl:template>
 
<xsl:template name="detail">
    <xsl:variable name="allFailureCount" select="count(/testResults/*[attribute::s='false'])" />
 
    <xsl:if test="$allFailureCount > 0">
        <h2>Failure Detail</h2>
 
        <xsl:for-each select="/testResults/*[not(@lb = preceding::*/@lb)]">
 
            <xsl:variable name="failureCount" select="count(../*[@lb = current()/@lb][attribute::s='false'])" />
 
            <xsl:if test="$failureCount > 0">
                <h3><xsl:value-of select="@lb" /><a><xsl:attribute name="name"><xsl:value-of select="@lb" /></xsl:attribute></a></h3>
 
                <table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
                <tr valign="top">
                    <th>Response</th>
                    <th>Failure Message</th>
                    <xsl:if test="$showData = 'y'">
                       <th>Response Data</th>
                    </xsl:if>
                </tr>
            
                <xsl:for-each select="/testResults/*[@lb = current()/@lb][attribute::s='false']">
                    <tr>
                        <td><xsl:value-of select="@rc | @rs" /> - <xsl:value-of select="@rm" /></td>
                        <td><xsl:value-of select="assertionResult/failureMessage" /></td>
                        <xsl:if test="$showData = 'y'">
                            <td><pre><xsl:value-of select="responseData" /></pre></td>
                        </xsl:if>
                    </tr>
                </xsl:for-each>
                
                </table>
            </xsl:if>
 
        </xsl:for-each>
    </xsl:if>
</xsl:template>
 
 
<!-- mystyle -->
<xsl:template name="myStyle">
        <h2>API请求详情</h2>
        <xsl:for-each select="/testResults/*[not(@lb = preceding::*/@lb)]">
                <h3><xsl:value-of select="@lb" /><a><xsl:attribute name="name"><xsl:value-of select="@lb" /></xsl:attribute></a></h3>
                <table align="center" class="details" border="0" cellpadding="5" cellspacing="2" width="95%">
                <tr valign="top">
                    <th>ResponseCode</th>
                    <th>RequestUrl</th>
                    <th>Response Data</th> 
                    <th>Response Header</th>               
                </tr>
                 <tr>
                    <td><xsl:value-of select="@rc | @rs" /> - <xsl:value-of select="@rm" /></td>               
                     <td class="data key"><pre class="data"><xsl:value-of select="method"/><xsl:text> </xsl:text><xsl:value-of select="java.net.URL"/></pre></td>    
                     <xsl:if test="$showData = 'y'">
                     <td class="data key"><pre><xsl:value-of select="responseData" /></pre></td>
                     </xsl:if>
                     <td class="data key"><pre class="data"><xsl:value-of select="responseHeader"/></pre></td>
                    </tr>
                </table>
        </xsl:for-each>
</xsl:template>
<!-- /mystyle -->
 
<xsl:template name="min">
    <xsl:param name="nodes" select="/.." />
    <xsl:choose>
        <xsl:when test="not($nodes)">NaN</xsl:when>
        <xsl:otherwise>
            <xsl:for-each select="$nodes">
                <xsl:sort data-type="number" />
                <xsl:if test="position() = 1">
                    <xsl:value-of select="number(.)" />
                </xsl:if>
            </xsl:for-each>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
 
<xsl:template name="max">
    <xsl:param name="nodes" select="/.." />
    <xsl:choose>
        <xsl:when test="not($nodes)">NaN</xsl:when>
        <xsl:otherwise>
            <xsl:for-each select="$nodes">
                <xsl:sort data-type="number" order="descending" />
                <xsl:if test="position() = 1">
                    <xsl:value-of select="number(.)" />
                </xsl:if>
            </xsl:for-each>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>
 
<xsl:template name="display-percent">
    <xsl:param name="value" />
    <xsl:value-of select="format-number($value,'0.00%')" />
</xsl:template>
 
<xsl:template name="display-time">
    <xsl:param name="value" />
    <xsl:value-of select="format-number($value,'0 ms')" />
</xsl:template>
    
</xsl:stylesheet>

 进入此路径,执行ant命令 

 如果build Successful,就可以看到生成的测试报告

在report文件夹下的测试报告,可以看出更加详细的请求和响应信息

数据加密

通过对数据加密,可以防止用户的重要数据被窃取

加密方式的分类

对称加密:数据的加密和解密使用同样一个密钥

非对称加密:使用公钥对数据加密,使用私钥解密。公钥是可以公开的,但是私钥是私有的

对称加密包括有:DES加密,AES加密,Base64加密

非对称加密包括:RSA加密

DES/AES加密:

将数据和加密所用的密钥一起结合处理,生成密文。

解密时,使用加密的逆算法,借助密钥,得到原文

缺点:1、要求解密方事先必须知道加密密钥  2、每一个用户使用的密钥是不一样的,这就导致要存储每一个用户的密钥

 优点:算法公开、计算量小、加密速度快、加密效率高

对admin进行AES、DES加密:

 

 解密得到admin

 

 这时,重复点击,对同一个字符串,生成的密文不是唯一的

Base64加密

Base64,就是包括小写字母a-z、大写字母A-Z、数字0-9、符号"+"、"/"一共64个字符的字符集,(另加一个“=”,实际是65个字符)

加密:

 解密:

 对同一个数据,生成的密文唯一

RSA加密

第一种方式:使用公钥加密,假设A拥有双钥,B想和A通信

1、A将公钥发给B

2、B使用公钥对数据加密,生成的密文交给A

3、A根据私钥解密,得到原数据

第二种方式:使用私钥加密,这里使用私钥对数据加密,称为数字签名,使用公钥解密,称为验证签名

因为使用公钥解密,公钥又是公开的,那么只要拿到了密文,就可以解密。所以,需要第三方(CA,数据证书颁发机构)来对使用的公钥进行加密(CA使用私钥加密我们使用的公钥),这样得到的数据,就是数字证书(包含用户的基本信息等)

 fidder抓取https协议的数据的过程:

因为https协议是http协议+ssl协议,使用了加密操作

fidder需要安装一个数字证书,CA机构会将生成的数字证书丢到官网,fidder获取获取一个数字证书生成器,从而从官网获取到了SSL协议的数字证书。

 MD5(不可逆)

MD5加密是一种哈希算法实现的加密方式,它是不可逆的(但是彩虹表可以实现简单的解密)

 

 

 接口签名

什么是接口签名:使用用户名,时间戳和所有排过序的参数组合起来之后,加密得到的密文

这个密文是唯一可以访问金融接口的鉴权码

防止恶意攻击,防止数据篡改,防止数据泄露,防止重复攻击(接口响应之后重复发送)

1、对所有请求的参数按照key,进行升序排列

比如:'a':'1',''b":''2","c":"3"

排列之后是 'a':'1',''b":''2","c":"3"

2、将参数名和参数内容设置成为字符串

a=1&b=2&c=3

3、使用用户名和密码在签名进行拼接,拼接到头部

appid:用户名 appsecret:密码

appid=admin&appsecret=123&a=1&b=2&c=3

4、用时间戳连接到字符串尾部

appid=admin&appsecret=123&a=1&b=2&c=3&timestamp=123456765432

5、使用32位MD5大写加密数据

F8E72B5DE945777961C859A70E4E82A4

6、一般10s中内有效

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值