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

【接口自动化】-11-接口加密签名 全局设置封装

一、RSA加密 

⭐ 先了解 RSA 加密的基本概念

RSA 是一种非对称加密算法,需要一对密钥:

  • 公钥(public key):用于加密数据,可公开(如放在服务器上供客户端使用)。
  • 私钥(private key):用于解密数据,必须保密(只有服务器持有)。

这段代码的作用是 “用公钥加密数据”,加密后的内容只能用对应的私钥解密,保证数据传输安全(如密码、token 等敏感信息)。

def rsa_encode(self, data):# 1. 加载公钥(用于加密)with open("../hotload/public.pem") as f:pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())  # 2. 转换为 UTF-8 编码的字节data = str(data).encode("utf-8")  # 3. 用公钥加密,得到字节数据byte_value = rsa.encrypt(data, pubkey)  # 4. Base64 编码(将字节转为可读字符串)rsa_value = base64.b64encode(byte_value).decode("utf-8")  return rsa_value

1. 加载公钥(第 3-4 行)
with open("../hotload/public.pem") as f:pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())

  • 作用:从文件中读取 RSA 公钥,用于后续加密。
  • 细节

    • ../hotload/public.pem 是公钥文件的路径(.pem 是常见的密钥文件格式)。
    • f.read() 读取文件内容(字符串),.encode() 转为字节(因为加密函数需要字节类型)。
    • rsa.PublicKey.load_pkcs1(...) 是 rsa 库的方法,将读取的字节数据解析为 “公钥对象”(供加密使用)。
2. 处理原始数据(第 6 行)
data = str(data).encode("utf-8")

  • 作用:将输入的原始数据(可能是字符串、数字等)转换为 RSA 加密要求的 “UTF-8 编码字节”。
  • 细节

    • str(data) 确保数据先转为字符串(避免数字、布尔值等类型直接加密报错)。
    • .encode("utf-8") 将字符串转为字节(RSA 加密算法只能处理字节数据)。
3. RSA 加密(第 8 行)
byte_value = rsa.encrypt(data, pubkey)

  • 作用:用公钥对处理后的字节数据进行加密。
  • 细节
    • rsa.encrypt(数据, 公钥) 是 rsa 库的加密方法,返回加密后的字节数据(无法直接阅读和传输)。
    • 加密后的结果 byte_value 是一串乱码字节(如 b'\x02\x1a...'),不适合在接口中直接传递。

4. Base64 编码(第 10 行)
rsa_value = base64.b64encode(byte_value).decode("utf-8")

  • 作用:将加密后的字节数据转换为 “可阅读、可传输的字符串”。
  • 细节

    • base64.b64encode(byte_value) 将字节数据转为 Base64 编码的字节(如 b'VGhpcyBpcyBhIHRlc3Q=')。
    • .decode("utf-8") 将 Base64 字节转为字符串(如 'VGhpcyBpcyBhIHRlc3Q='),方便在接口参数中传递。
5. 返回结果(第 12 行)
return rsa_value

  • 最终返回的是 “RSA 加密后再 Base64 编码的字符串”,可以安全地在网络中传输。

⭐ 举例:实际加密效果

假设输入数据是字符串 "mypassword123",执行函数后:

  1. 公钥从 public.pem 中加载成功。
  2. 数据转为字节:b'mypassword123'
  3. RSA 加密后得到字节:b'\x02\x1a\x03...'(乱码)。
  4. Base64 编码后得到字符串:'QZ5fD...x2aA=='(可传输)。

接收方用对应的私钥解密后,能还原出原始数据 "mypassword123"

⭐ 为什么要这样设计?

  1. RSA 加密保证安全性:只有持有私钥的一方才能解密,防止数据被窃取后泄露。
  2. Base64 编码解决传输问题:RSA 加密结果是字节,无法直接在接口参数(通常要求字符串)中传输,Base64 能将字节转为安全的字符串。
  3. 通用性:将加密逻辑封装为函数,可在测试用例中通过 ${rsa_encode(数据)} 直接调用(如之前学习的 YAML 用例)。

⭐ 总结

这段代码的核心流程是:
加载公钥 → 数据转为字节 → RSA加密 → Base64编码 → 返回字符串

作用是将敏感数据(如密码)通过 RSA 加密,转换为可传输的字符串,确保接口传输过程中的安全性。理解后,你可以:

  • 替换 public.pem 路径,使用自己的公钥文件。
  • 在接口测试用例中调用该函数,加密需要保护的参数。
  • 结合私钥解密代码(通常在服务器端),验证加密是否正确。

二、加密参数处理 

⭐ 功能模块划分

模块作用
debug_talk.py实现 加密工具函数(MD5、Base64、RSA 加密),供 YAML 用例调用
*.yaml(如 md5.yaml定义 接口用例(请求信息、加密参数占位符、断言)
requests_util.py实现 请求发送核心逻辑send_all_requests 类 / 函数,处理加密参数、发送请求)

⭐ debug_talk.py:加密工具函数解析

1. MD5 加密(md5_encode
def md5_encode(self, data):# 1. 转换为 UTF-8 编码的字节data = str(data).encode("utf-8")  # 2. MD5 加密(哈希算法),生成十六进制结果md5_value = hashlib.md5(data).hexdigest()  return md5_value

  • 作用:将输入数据(如 admin)转为 MD5 加密字符串(如 21232f297a57a5a743894a0e4a801fc3)。

2. Base64 加密(base64_encode
def base64_encode(self, data):# 1. 转换为 UTF-8 编码的字节data = str(data).encode("utf-8")  # 2. Base64 加密,再解码为字符串base64_value = base64.b64encode(data).decode("utf-8")  return base64_value

  • 作用:将输入数据(如 admin)转为 Base64 编码字符串(如 YWRtaW4=)。

3. RSA 加密(rsa_encode
def rsa_encode(self, data):# 1. 加载公钥(用于加密)with open("../hotload/public.pem") as f:pubkey = rsa.PublicKey.load_pkcs1(f.read().encode())  # 2. 转换为 UTF-8 编码的字节data = str(data).encode("utf-8")  # 3. 用公钥加密,得到字节数据byte_value = rsa.encrypt(data, pubkey)  # 4. Base64 编码(将字节转为可读字符串)rsa_value = base64.b64encode(byte_value).decode("utf-8")  return rsa_value

  • 作用:用 RSA 公钥加密数据,再通过 Base64 编码转为字符串(RSA 加密结果是字节,需 Base64 转成接口可传的字符串)。

⭐ *.yaml:接口用例定义

以 md5.yaml 为例:

feature: 加密模块
story: md5加密接口
title: md5加密接口
request:method: posturl: http://101.34.221.219:5000/md5logindata:username: ${md5_encode(admin)}  # 调用md5_encode加密password: ${md5_encode(123)}    # 调用md5_encode加密
validate:equals:断言状态码为200: [200, status_code]

  • 关键${md5_encode(admin)} 是函数占位符,框架会自动调用 debug_talk.py 中的 md5_encode 函数,将结果替换到请求参数中。

⭐ requests_util.py:请求发送核心逻辑

class RequestUtil:sess = requests.Session()  # 会话对象,保持cookie等def send_request(self, **kwargs):# 处理加密参数(框架会自动识别${函数名(...)}并调用对应加密函数)# 此处省略“解析YAML中函数占位符并替换为加密结果”的逻辑(需结合框架上下文)# 发送请求res = self.sess.request(**kwargs)  # 用requests发送请求,**kwargs是请求参数(method/url/data等)# 处理响应(日志记录)if "json" in res.headers.get("Content-Type", ""):logger.info(res.json())  # 响应是JSON,记录JSON内容else:logger.info(res.text)    # 响应非JSON,记录文本内容return res
  • headers.get("Content-Type", "") 是字典的 get 方法,作用是:

    • 尝试获取响应头中 Content-Type 字段的值(这个字段用于说明响应内容的格式)。
    • 如果 Content-Type 不存在,就返回默认值 ""(空字符串),避免报错。
  • 作用

    1. 接收 YAML 中定义的请求参数(已替换加密后的参数)。
    2. 发送 HTTP 请求,获取响应。
    3. 根据响应类型(JSON / 非 JSON)记录日志,便于调试。

⭐ 与之前代码的联系(数据驱动 + 加密的整合)

  1. 数据驱动与加密的结合
    之前的 parametrize 实现了 “多组数据驱动单接口”,现在在此基础上,用例中的参数可以是 “加密后的数据”(通过 debug_talk.py 的函数生成)。

  2. 请求发送的统一入口
    之前的 send_all_requests 负责 “发送普通请求”,现在升级为 “发送带加密参数的请求”—— 框架会先解析 YAML 中的加密占位符(如 ${md5_encode(admin)}),调用 debug_talk.py 生成加密值,再传递给 send_request 发送。

⭐ 整体流程总结

  1. 编写用例:在 YAML 中用 ${加密函数(参数)} 定义需要加密的参数。
  2. 解析用例:框架识别 ${...} 占位符,调用 debug_talk.py 中的对应加密函数,生成加密后的值。
  3. 发送请求requests_util.py 接收替换后的参数,发送 HTTP 请求。
  4. 处理响应:记录响应日志,完成接口测试。

三、接口签名 

首先,“签名” 你可以理解成给数据盖个 “防伪章”。为啥要盖呢?就像你寄贵重快递,怕路上被人偷偷拆开换了东西,所以搞个只有你和收件方知道的 “暗号章”,收件方一看章对,就知道东西没被动过。接口签名也是这作用,防止别人在网络传输里篡改你要发的数据。

第一步:挑出要盖印的 “材料”(选参数)

要发的参数里,空的、没用的就别要了(比如有的参数值是空,就不参与签名),然后把剩下有用的参数,按照参数名的字母顺序排好队。比如参数有acm这些,就按字母顺序排,排好后用 “key=value&key=value” 这种格式连起来,变成一个字符串,叫stringA

第二步:加上 “秘密暗号”(加密钥)

把第一步弄好的stringA,再加上一个只有你和接口提供方知道的 “秘密字符串”(叫key,就像只有你俩知道的暗号),拼成新的字符串stringSignTemp

第三步:生成 “防伪章”(算 MD5 并大写)

用一种叫 MD5 的算法,把stringSignTemp变成一串固定长度的字符,然后把这串字符全改成大写,这就是最终的 “签名”(sign)啦。

最后咋用?

把这个sign放到请求里发过去,接口那边收到后,会用同样的步骤(选参数、排序、加key、算 MD5 大写)也生成一个sign,然后和你发的对比。要是一样,就说明数据没被篡改,是合法请求;不一样,就说明数据被人动过,接口就会拒绝。

  • 首先列出了 a=dorun、c=login、m=u、backurl=xxx、username=baili、password=baili123 这些参数。
  • “stringA = a=dorun&c=login&m=u&backurl=xxx”:按照第一张图里的第一步,把这些参数按照参数名 ASCII 码从小到大排序后,用 URL 键值对格式拼接成了 stringA。
  • “stringSignTemp = a=dorun&c=login&m=u&backurl=xxx&key=?”:在 stringA 的基础上拼接上 key(这里用?表示,实际应该是具体的 key 值),得到 stringSignTemp。
  • “md5_value = md5(stringSignTemp)”:对 stringSignTemp 进行 MD5 运算,得到 md5_value。
  • “sign = md5_value.upper()”:把 md5_value 转换成大写,得到 sign。
  • sign 的值一般是放到请求头里面。

四、setting.py 

# 数据库连接配置
db_username = "sdm723416659"
db_password = "Msjy123456"
db_database = "sdm723416659_db"
db_host = "sdm723416659.my3w.com"
db_port = 3306# 全局公共请求参数
global_args = {"application": "app","application_client_type": "h5"
}# 接口自动化中间变量存储文件
extract_name = "extracts.yaml"# 测试报告配置
allure_project_name = "金融项目接口自动化报告"

1. conn_database方法用于连接数据库。连接数据库时需要的用户名(user)、密码(password等参数,没有直接写死在代码里,而是通过setting.db_username这种方式从setting.py文件中获取。
好处:如果数据库信息变了,比如换了密码,只改setting.py里的db_password就行,不用改这个工具类的代码。

2. global_args是所有接口请求都需要带的公共参数,比如"application": "app",所有接口都会用到这两个参数。send_all_request方法里有一行kwargs["params"].update(setting.global_args),意思是把setting.py里的global_args公共参数,自动添加到每个接口请求的参数里。

好处:如果所有接口的公共参数需要改(比如把"h5"改成"pc"),只改setting.py里的global_args,不用每个接口都改一遍。

3.extract_name = "extracts.yaml":规定了存储接口之间传递的中间变量的文件名,比如一个接口返回的 token 需要给另一个接口用,就存在这个文件里。

好处:这样提取到setting配置文件,这个文件的名字可以随便起都行。extract_name = "cyf.yaml"也行

4.allure_project_name:规定了生成的测试报告的项目名称,这样报告的标题就统一由这里控制。

总结:setting.py就像一个 “中央配置中心”,把原来散落在各个代码文件里的固定值(比如数据库密码、公共参数)都集中到这里,改配置时只用动这一个文件,极大减少了改代码的工作量。

然后,我们平时只要维护setting和debug_util这两个文件和新增编写yaml就行啦。这个框架几乎就完成啦。

http://www.xdnf.cn/news/17665.html

相关文章:

  • 容器安全扫描工具在海外云服务器环境的集成方法
  • Element用法---Loading 加载
  • npm、pnpm、yarn区别
  • 一周学会Matplotlib3 Python 数据可视化-绘制饼状图(Pie)
  • 前沿技术借鉴研讨-2025.8.12 (数据不平衡问题)
  • Web项目Excel文件处理:前端 vs. 后端,企业级如何选择?
  • 【3】Transformers快速入门:大语言模型LLM是啥?
  • 11-docker单机版的容器编排工具docker-compose基本使用
  • centos 7 如何安装 ZipArchive 扩展
  • MySQL 数据库表操作与查询实战案例
  • MySQL概述
  • 计算机网络:ovn数据通信都是用了哪些协议?
  • 集成电路学习:什么是URDF Model统一机器人描述格式模型
  • 智能合约执行引擎在Hyperchain中的作用
  • 北京-4年功能测试2年空窗-报培训班学测开-第七十三天-投递简历-[特殊字符][特殊字符]
  • LangChain 框架 Parser 讲解
  • 介绍一下jQuery的AJAX异步请求
  • Nacos-1--什么是Nacos?
  • vue+flask基于规则的求职推荐系统
  • 3Ds Max的魔改利器:RailClone - 程序化建模的革命者
  • Linux Web服务器与WordPress部署笔记
  • DNS 服务详解与 BIND 部署
  • Django ORM查询技巧全解析
  • 基于Springboot+UniApp+Ai实现模拟面试小工具九:移动端框架搭建
  • 第二章:变量与简单数据类型
  • 【lucene】livedocs描述
  • 【华为机试】208. 实现 Trie (前缀树)
  • 图像打标工具/方法的分类和特点说明
  • Launcher3启动
  • 实战:用 PyTorch 复现一个 3 层全连接网络,训练 MNIST,达到 95%+ 准确率