当前位置: 首页 > article >正文

使用Apifox动态生成请求参数

比如,我要调试一个登录请求,使用Apifox来进行调试,登录请求需要一个密码,这个密码需要进行AES加密后才能发送出去,我希望在Apifox中我填入明文密码,然后Apifox帮我进行AES加密后再发送出去。

我的登录使用的是Kotlin语言(属于Java语言),所以我希望用的Kotlin代码去加密,在IntelliJ中,创建一个使用gradle的Kotlin项目,截图如下:
在这里插入图片描述
然后在该项目中加入Aes加密的代码,项目结构如下:
在这里插入图片描述
Aes.kt实现如下:

import java.util.*
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec

object Aes {

    /** 使用AES进行加密,加密后的数据使用Base64编码为String */
    fun encrypt(rawData: String): String = Base64.getEncoder().encodeToString(getCipher(Cipher.ENCRYPT_MODE).doFinal(rawData.toByteArray()))

    /** 把AES加密并通过Base64编码的String进行解密,还原为原始的String */
    fun decrypt(base64Data: String): String = String(getCipher(Cipher.DECRYPT_MODE).doFinal(Base64.getDecoder().decode(base64Data)))

    private fun getCipher(mode: Int) = Cipher.getInstance("AES/ECB/PKCS5Padding").apply { init(mode, SecretKeySpec("99cdefgabcdefg88".toByteArray(), "AES")) }

}

Main.kt实现如下:

fun main(args: Array<String>)  {
    if (args.isEmpty()) {
        println("无运行参数")
        return
    }

    selectAction(args)
}

fun selectAction(args: Array<String>) {
    val action = args[0]
    when (action) {
        "aes" -> aes(args)
    }
}

fun aes(args: Array<String>) {
    val data = args[1]
    val encrypt = Aes.encrypt(data)
    println(encrypt)
}

运行main函数时传入两个参数,第一个参数传aes,则我们就会调用AES加密第二个参数,并把加密结果输出到控制台(这样设计是为了方便扩展,比如后面可能还有别的功能,比如生成检验码)。Apifox会读取我们的输出,所以它可以拿到加密后的内容。Apifox并不能直接执行kotlin或java源文件,它只能执行jar包,所以我们需要把kotlin项目打成一个可执行jar,在build.gradle.kts中添加一个tasks.jar的任务,如下:

plugins {
    kotlin("jvm") version "1.9.23"
}

group = "cn.dazhou.api.util"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    testImplementation("org.jetbrains.kotlin:kotlin-test")
}

tasks.test {
    useJUnitPlatform()
}
kotlin {
    jvmToolchain(11)
}
tasks.jar {
    archiveFileName.set("ApiUtil.jar")
    manifest {
        attributes["Main-Class"] = "cn.dazhou.api.util.MainKt"
    }
    from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) })
}

如上代码,除了tasks.jar这个任务代码,其它都是创建项目时自动生成的,archiveFileName用于设置生成的jar的文件名,manifest 中设置了main函数的类是哪一个类。

双击执行gradle面板中的jar任务即可生成一个可执行jar,截图如下:
在这里插入图片描述
生成的jar在build/libs目录下:
在这里插入图片描述
打开Apifox,我们使用apifox官方提供的简单请求测试接口https://echo.apifox.com/post,我们设置为post请求,并添加一个password参数为123456,然后发送请求,结果如下:

在这里插入图片描述
如上图,可以看到响应结果中,服务器收到了明文的密码。

点击Apifox右上角的设置按钮,然后点击 “外部程序” ,在这里可以看到外部程序的目录,点击“打开目录”按钮,然后把我们的ApiUtil.jar复制到这个目录中,如下图,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
回到Apifox的快捷请求界面,点击 “前置操作”,然后添加一个自定义脚本,截图如下:
在这里插入图片描述
在这里插入图片描述
这是javascript语言,一些具体逻辑不知道怎么写的可以直接问DeepSeek,上面代码功能应该也不用解释了,一看就懂了,功能就是读取post请求中urlencoded中的password参数,然后调用我们的ApiUtil.jar进行加密,加密后把原来的password参数移除,然后添加经过加密后的参数。再次发送请求,结果如下:
在这里插入图片描述
如上图,可以看到响应体中的密码就是加密后的密码了,后面再调试时,我们密码随便换,只需要填入明文密码,工具会自动帮我们加密。

另外,需要注意的是,如果请求参数使用的是form-data类型,则代码中应该是以pm.request.body.formdata来读取参数,如果使用的是x-www.form-urlencoded类型,则是以pm.request.body.urlencoded来读取参数。form-data(即multipart/form-data)和x-www-form-urlencoded(即application/x-www-form-urlencoded)是两种常见的表单数据编码方式,它们之间的区别可以直接问DeepSeek,简单来说,如果只传文本参数使用x-www-form-urlencoded,如果要传文件或者文件加文本,则用form-data

前置操作中默认就一个前置操作,叫 “变量替换” 拖动左侧的6个点可以上下调整位置,如下图:
在这里插入图片描述
这个上下位置的顺序决定了它们的执行顺序,比如“变量替换”在上方,则Apifox会先执行变量替换,再执行我们的自定义脚本。假如“自定义脚本” 在上面,如果我们在自定义脚本中想读取替换后的变量,则会读取不到,因为自定义脚本运行时,变量替换的脚本还没有运行。具体可以查看官方文档,我当时问过Apifox交流群,给出的一些链接如下:

  • Apifox支持通过调用外部程序,调用在 “外部程序目录” 中的可执行代码文件。这些文件可以是:Java 程序归档文件(JAR 包)、其它编程语言的源代码文件、可执行脚本文件。
    使用方式请参考帮助文档☞https://docs.apifox.com/5586304m0

  • 在请求接口的过程中,通常需要将已引用的变量转换为真实的请求数据。某些高安全等级接口会要求请求数据需要加密 / 签名,便需要针对完整的请求数据进行签名处理,最后再将加密数据发送至服务端口。
    为了解决接口加密 / 签名问题,可以在 Apifox 的「前置操作」环节中对整个请求数据进行签名处理以满足接口的安全要求。
    注意:若“自定义脚本”放置在“变量替换”步骤之后,那么签名脚本可以获取到变量替换后的实际请求数据。否则只能获取到替换之前的数据
    详细说明请参考☞ https://docs.apifox.com/5831263m0#%E8%BF%90%E8%A1%8C%E8%84%9A%E6%9C%AC
    接口签名更多示例☞ https://docs.apifox.com/5802226m0

扩展:

把前面的示例扩展一下,比如登录时还需要传本机ip参数,在Kotlin项目中,我们添加一个Utils类,用于封装各种工具函数,比如获取IP地址的函数,代码如下:

object Utils {

    fun getActiveIPv4Address(): String = try {
        // 使用 Google 的公共 DNS 作为目标(无需实际连接)
        Socket().use { socket ->
            socket.connect(InetSocketAddress("8.8.8.8", 53), 1000)
            val localAddress = socket.localAddress as? Inet4Address
            socket.close()
            localAddress?.hostAddress ?: ""
        }
    } catch (e: Exception) {
        ""
    }

}

Main.kt如下:

fun main(args: Array<String>)  {
    if (args.isEmpty()) {
        println("无运行参数")
        return
    }

    selectAction(args)
}

fun selectAction(args: Array<String>) {
    val action = args[0]
    when (action) {
        "aes" -> aes(args)
        "ip" -> ip()
    }
}

fun ip() {
    val ip = Utils.getActiveIPv4Address()
    println(ip)
}

fun aes(args: Array<String>) {
    val data = args[1]
    val encrypt = Aes.encrypt(data)
    println(encrypt)
}

如上代码,如果要获取ip,运行main函数时只需要输入一个参数ip即可。然后重新生成一个jar文件,覆盖到Apifox指定的目录中。

然后在登录请求中添加ip参数,如下:
在这里插入图片描述
如上图,{{ip}}表示读取环境变量ip,我们在自定义脚本中就可以为这个环境变量赋值,点击 前置脚本,添加如下脚本代码:
在这里插入图片描述
这里一定要注意,需要把 “变量替换” 放在 “自定义脚本” 下面,如下:
在这里插入图片描述

为什么要这样呢?因为我们的自定义脚本只是设置了一个环境变量,具体把环境变量取出来替换到请求参数中是由 “变量替换” 这个脚本完成的,如果 “变量替换” 在上面,则变量替换会先执行,但是这时ip这个环境变量还没设置有值,那么发送请求时ip的值将原样发送,即发送 “{{ip}}”,所以要让自定义脚本运行,这样自定义脚本就会先给环境变量赋值了,这样再到变量替换执行时,就可以把真正的ip替换到{{ip}}上了,执行结果如下:
在这里插入图片描述

对于变量,有三种类型:全局/环境/临时变量,具体参考官方文档:https://docs.apifox.com/5537409m0


http://www.kler.cn/a/564478.html

相关文章:

  • 如何将mobaxterm的默认编辑器修改为vscode
  • 深入浅出:插入排序算法完全解析
  • Java中,Scanner和System.out超时的解决方法及原理
  • 【含文档+PPT+源码】基于过滤协同算法的旅游推荐管理系统设计与实现
  • Spring Boot + JSqlParser:全面解析数据隔离最佳实践
  • 左值引用与右值引用详解
  • Autosar_RTE基础概念整理
  • 为AI聊天工具添加一个知识系统 之125 详细设计之66 智能语义网络
  • leetcode 912. 排序数组
  • 需求: 使用 minio 做一个 企业微信对话的下载、存储,利用deepseek进行对话回复
  • 在VSCode中安装jupyter跑.ipynb格式文件
  • PhpStorm 绿色版 安装包 Win/Mac/Linux 商业的PHP集成开发环境 2025全栈开发终极指南:从零配置到企业级实战
  • 腾讯云的海外轻量云套餐
  • 【学写LibreCAD】3 qmetaobject库介绍
  • Pytorch加载数据的Dateset类和DataLoader类
  • .hive-staging_hive临时文件处理
  • 【人工智能】数据挖掘与应用题库(201-300)
  • Python连接SQL SEVER数据库全流程
  • python 网络安全常用库 python做网络安全
  • Cookie与Session:Web开发中的状态管理机制