一般接口开发中有以下常用的几种安全机制:
- 用户认证
- 数字签名
- 接口加密
用户认证
一般的接口测试工具都会提供一个User Auth/Authorization的选项,以Postman为例子,你可以看到以下的选项:
- 基本认证(Basic Auth)
- 摘要认证(Digest Auth)
- OAuth 1.0a
- OAuth 2.0(最常见,现在的网站接口多数提供此用户认证方式)
在对应的工具上,你可以选取对应的用户认证选项,这里主要介绍如果用Python如何实现用户认证。1 首先安装Requests库,Requests库的get()和post()方法均提供有auth参数,用于设置用户签名。
2 假定我们有一个接口为添加一个新的公告,接口需要认证:auth=("username","password")
nid 或 name两个参数二选一
3 伪代码:def test_get_notice_list_nid_sucess(self): auth_user = ('admin' , 'admin123456') r = requests.get(self.base_url, auth = auth_user, params = {'nid' : 1}) result = r.json() self.assertEqual(result['status'], 200) ....
数字签名
在使用 HTTP/SOAP 协议传输数据的时候,签名作为其中一个参数,可以起到关键作用:
先来一个简单的,通过客户的密钥,服务端的密钥匹配;
这个很有好理解,例如一个接口传参为:
http://127.0.0.1:8000/api/?a=1&b=2
假设签名的密钥为:@signpassword
加上签名之后的接口参数为:
http://127.0.0.1:8000/sign/?a=1&b=2&sign=@signpassword
但是,这样的sign 参数明文传输是不安全的,一般会选择一些加密算法,比如MD5 算法(MD5算法是不可逆向的),比如MD5代码如下:
import hashlib
md5 = hashlib.md5()
sign_str = "@signpassword"
sign_bytes_utf8 = sign_str.encode()
md5.update(sign_bytes_utf8)
sign_md5 = md5.hexdigest()
print(sign_md5)
执行后得到:6648e929329e53e7a91c50ae685a88b5
此时带签名的接口为:
http://127.0.0.1:8000/sign/?a=1&b=2&sign=6648e929329e53e7a91c50ae685a88b5
所以,当服务器接收到请求后,同样需要对“signpassword”进行 MD5 加密,然后,比对与调用者传来的 sign 加密串是否一致,从而来鉴别调用者是否有权限使用该接口。
接着,我们来理解一个复杂一点的:把sign参数传递为api key(申请获取)+timestramp(时间戳)同样需要 用代码来实现,原理和上面这个一致的。(伪代码)
def setUp(self):
self.base_url = "http://127.0.0.1:8000/api/sec_add_notice/"
# app_key
self.api_key = "&APIkey"
# 当前时间
now_time = time()
self.client_time = str(now_time).split('.')[0]
# sign
md5 = hashlib.md5()
sign_str = self.client_time + self.api_key
sign_bytes_utf8 = sign_str.encode(encoding="utf-8")
md5.update(sign_bytes_utf8)
self.sign_md5 = md5.hexdigest()
接口加密
通常接口会使用更复杂一点的方式来进行加密的操作,常见的是AES的使用,放一张图让大家感受一下AES加解密的过程:
详细的过程可以参见http://www.mamicode.com/info-detail-514466.html 或者自行百度。
Python里面有一个很好的黑魔法,叫PyCrypto库,支持常见的 DES、AES 加密以及 MD5、SHA 各种 HASH 运算。(官方网站下载最新版本:https://www.dlitz.net/software/pycrypto/
另外,也可以在 PyPi 仓库中下载安装:https://pypi.python.org/pypi/pycrypto)
对于AES的加密来说,看一下用了PyCrypto库的结果
加密:
from Crypto.Cipher import AES
# 加密
obj = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
message = "The answer is no"
ciphertext = obj.encrypt(message)
print(ciphertext)
程序运行后的结果为:b'xd6x83x8dd!VTx92xaa`Ax05xe0x9bx8bxf1'
AES加密里面有两个关键,一个是key(必须为16,24,32位),一个是VI(必须为16位)
解密:解谜者必须要同时知道key和VI才可以解密
obj2 = AES.new('This is a key123', AES.MODE_CBC, 'This is an IV456')
s = obj2.decrypt(ciphertext)
print(s)
===
So,接口加密测试的关键就在于开发小哥哥们用了什么加密算法来加密接口。你用相同的加密算法来加密你要发送的值 即可。
现在有很多的公司也把加密的算法直接封装成一个类或者一个接口,也就是测试的时候,你直接调用加密的类或者加密的接口即可完成你的加密工作。剩下的接口测试和以往没加密的接口测试一样没两样了。
附送一个Pypi库里一堆加密算法库的链接,自取:
https://pypi.python.org/pypi?%3Aaction=search&term=crypt&submit=search