为什么要签名?
1、防止接口被恶意调用,增加服务器的压力
2、保证数据的一致性(即发送和收的的数据相同)
签名校验原理?
1、简单点的理解就是客户端发送{"username":"jack","password":"aaa123456"}给服务端,通过一个key="hello world"加入到你的请求体里面,然后通过一系列方式得到一个sign,你的发送数据变成{"username":"jack","password":"aaa123456","sign":"DKAG663F"}
2、服务端得到数据之后,去除sign字段,得到客户端需要发送的真实请求数据,然后用相同的key="hello world",用相同的手段对其进行加密,同样得到一个new_sign,如果sign==new_sign,那证明是自己人请求的,数据也没用被修改,因为key只有我俩自己知道,否则就是他人请求的,给与拒绝
搞清楚为什么要进行签名和签名的基本原理了,现在实现一个简单的签名已经验签,直接上代码,本文是以MD5的方式进行加密,其他的方式基本原理也一样
a、新建一个目录sign_test,目录下我建了三个python文件,get_sign.py,requests_server.py,requests_client.py
b、get_sign.py
import hashlib # 导入模块hashlib
# md5加密算法
def MD5(str):
'''
:param str: 需要加密的字符串
:return: 加密完成的密文
'''
md = hashlib.md5() # 创建md5对象
md.update(str.encode(encoding='utf-8'))
return md.hexdigest()
# 获取sign签名
def getSign(map: dict, key: str):
'''
:param map: 接口的请求数据
:param key: 客户端与服务端约定的key
:return: 签名
'''
# 遍历字典,组成特定格式(k1=v1&)字符串的列表
li = [(k, map[k]) for k in sorted(map.keys())]
result = ""
for i in li:
result += i[0] + "=" + i[1] + "&"
# print(result) result=password=aaa123456&username=jack&
result_new = result + 'key=' + key
# print(result_new)result_new=password=aaa123456&username=jack&key=hello
# md5加密,并转为大写。
sign = MD5(result_new).upper()
# 返回sign
return sign #95E34CB05C944D33DE166E03942C83B3
if __name__ == '__main__':
body={"username":"jack","password":"aaa123456"}
key="hello"
sign=get_sign(body,key)
print(sign)
c、requests_server.py,启动一个服务端进行验签
from flask import Flask, request
import json
from flask_cors import CORS
from sign_test.get_sign import get_sign
app = Flask(__name__)
# 允许跨域
CORS(app, resources=r'*')
@app.route('/api', methods=['POST'])
def api():
data = json.loads(request.data)
print("请求体的数据:{}".format(data))
sign = data["sign"]
del data["sign"]
# 将请求的数据去除sign之后,用相同的key去加密,得到一个new_sign
new_sign = get_sign(data, key="hello")
print("服务端的签名:{}".format(new_sign))
# 判断客户端发过来的签名是否与服务端的签名一致
if sign == new_sign:
'''do something
、、、
、、、
'''
res = {"status": 200, }
return json.dumps(res)
else:
return json.dumps({"status": 500})
if __name__ == '__main__':
app.run(host='localhost', port=8009, debug=True)
d、requests_client.py
from sign_test.get_sign import get_sign
import requests, json
# 主程序
if __name__ == "__main__":
# 加密秘钥
key = "hello"#key是双方约定的,我这边就是直接写死一个,与服务端一直
body = {"username": "alex", "pwd": "123456"}
sign = get_sign(body, key)
body["sign"] = sign
url="http://localhost:8009/api"
res = requests.post(url=url, data=json.dumps(body))
print("请求体body={}".format(body))
print("返回值:{}".format(json.loads(res.content)))
e、保持key="hello",启动服务,发送请求
客户端
请求体body={'username': 'alex', 'pwd': '123456', 'sign':'E9C952A9F32719995319149991365D15'}
返回值:{'status': 200}
服务端
请求体的数据:{'username': 'alex', 'pwd': '123456', 'sign': 'E9C952A9F32719995319149991365D15'}
服务端的签名:E9C952A9F32719995319149991365D15
签名和验签都是成功的!!!!!!!!!!!!!
f、保持服务端key="hello",客户端key=world启动服务,发送请求
客户端
请求体body={'username': 'alex', 'pwd': '123456', 'sign': 'DFB02DEE70B5B9D3CD8B446051EF3A84'}
返回值:{'status': 500}
服务端
请求体的数据:{'username': 'alex', 'pwd': '123456', 'sign': 'DFB02DEE70B5B9D3CD8B446051EF3A84'}
服务端的签名:E9C952A9F32719995319149991365D15
客户端返回的是500,验签是失败的,因key不一致!!!!
本文采用的是MD5进行的加密,由于MD5加密是不可逆的,所以一般可以用来签名或者校验文件的完整性,原理都是一样的,现在签名和加密用的较多的就是RSA和AES算法,基本上用法都差不多,文中有错误的欢迎指出,有兴趣测试或者开发伙伴欢迎来一起探讨