本文为博主原创,未经授权,严禁转载及使用。
本文链接:https://blog.youkuaiyun.com/zyooooxie/article/details/109023145
前些天接了一个需求,测完 我觉得:这个需求应该是我从业以来,最要求代码能力的需求了。
【实际这篇博客推迟发布N个月】
个人博客:https://blog.youkuaiyun.com/zyooooxie
【以下所有内容仅为个人项目经历,如有不同,纯属正常】
需求
某个业务系统 要给外部提供一个接口,用来实现某些功能。
实际传参字段包括电话号码、签名、时间戳等等;用户电话及签名 都使用我们现有的加解密规则;
其实看到 加密,我就来了兴趣,因为之前曾经做过2次分享 :RSA加解密 ;
AES加解密、异或、MD5。
接口文档
请求参数如下 特别修改过
属性 | 属性名 | 备注 |
---|---|---|
手机号 | mobile | 经过(AES+base64)加密后的手机号 |
签名 | sign | (手机号+sk+时间戳) 进行sha512加密 |
时间戳 | timestamp | 生产环境 将做N秒内的校验 |
加密结果、方式如下 特别修改过
测试手机号: 1234567890
AES+base64加密后 : AES1234567890==
时间戳:1638628427000【最后一版:2021-12-04 22:33:47】
Sign加密后:Sign1234567890==
- 手机号加密(AES+base64) 测试环境 key : zyooooxie
Java代码 修改过、部分代码未展示
public static String aesEncryptByBase64(String key, String context) {
return aesEncrypt(Mode.ECB, Padding.PKCS5Padding, key, "", context);
}
- 签名加密(sha512) 测试环境 sk : ZYOOOOXIE
Java代码 修改过、部分代码未展示
private static String genSign(String timestamp, String body, String sk) {
if (StringUtils.isEmpty(body)) {
body = "";
}
StringBuffer sb = new StringBuffer();
sb.append(timestamp);
sb.append("&").append(body);
sb.append("&").append(sk);
byte[] bytes = DigestUtils.sha512(sb.toString());
return Base64.encodeBase64URLSafeString(bytes);
}
返回的错误码、实际请求和返回值示例 就不做展示。
测试过程、代码
之前分享过 做接口测试 我的思路 https://blog.youkuaiyun.com/zyooooxie/article/details/114380007 ;
实际测试过程
某个周二下午3点 拿到接口文档;
3点半 校验mobile字段值 加密pass;
4点 校验sign 字段值 出错;
4点半 后台同事特地发我2个 更底层的方法 (暂无法展示);
9点半 我在家远程 搞出来了;(Python 和 Java的使用方法不同,再加上 我菜)
周三上午9点半 我用JMeter发请求,死活调不通(Json字符串 有问题);
10点 决定使用requests 来发请求;
10点半 校验sign 字段值 加密pass;(Python的结果 需要特殊处理下)
之后 才开始测试。
代码
encrypt_func() 见 AES加解密、异或、MD5
import requests
import time
import base64
import hashlib
import string
import random
from xxx_use.ase_encrypt_decrypt import encrypt_func
from user_log import Log
class TwMem(object):
KEY = 'zyooooxie'
SK = 'ZYOOOOXIE'
URL = 'https://blog.youkuaiyun.com/zyooooxie'
def __init__(self, phone: str):
self.__ph = phone
@property
def mobile(self):
"""
接口中 mobile参数
:return:
"""
abc = encrypt_func(self.__ph, key=self.KEY)
return abc
@property
def sign(self):
"""
接口中 sign参数
:return:
"""
now = int(time.time() * 1000)
Log.info('现在时间戳:{}'.format(now))
Log.info('现在sk:{}'.format(self.SK))
Log.info('现在加密key:{}'.format(self.KEY))
m = hashlib.sha512()
test_str = '&'.join(['{}'.format(now), self.mobile, '{}'.format(self.SK)])
Log.info(test_str)
m.update(test_str.encode())
res = m.digest() # 返回 bytes
# hash.digest() 返回摘要,作为二进制数据字符串值
# hash.hexdigest() 返回摘要,作为十六进制数据字符串值
# print('加密后为 :' + str(base64.urlsafe_b64encode(res), "utf-8"))
abc = base64.b64encode(res).decode()
abc = abc.replace('+', '-').replace('/', '_') # 为了符合 (Java 计算得出的结果),特意做的处理
Log.info(abc)
return now, abc[:-2]
def req(self):
t, s = self.sign
test = {
"mobile": self.mobile,
"timestamp": t,
"sign": s,
"Code": ''.join(random.sample(string.zy, 9)) # string.zy 是我修改string的源码 新增的; zy = digits + ascii_letters
}
Log.info(test)
res = requests.post(self.URL, json=test)
Log.info(res.json())
if __name__ == '__main__':
pass
tw = TwMem('0999999999')
# print(tw.__dict__)
# print(tw.mobile)
# 使用@property装饰器修饰 mobile方法后,就可以像使用属性一样使用。【调用时不需要写后面的小括号】
# 如果你希望可以对mobile进行赋值,那么需要用@mobile.setter装饰器再装饰一个方法,完成对mobile属性的赋值操作。
# 而且 不必担心有人对其进行赋值操作,这种代码一定会报错的。
# tw.mobile = 1 # AttributeError: can't set attribute
# del tw.mobile # AttributeError: can't delete attribute
# tw.req()
我用了3年半去积累,写出来90行代码,才能测这个需求。
真的是很感慨。
本文链接:https://blog.youkuaiyun.com/zyooooxie/article/details/109023145
交流技术 欢迎+QQ 153132336 zy
个人博客 https://blog.youkuaiyun.com/zyooooxie