python关于接口的签名和验签的简单示例

为什么要签名?
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算法,基本上用法都差不多,文中有错误的欢迎指出,有兴趣测试或者开发伙伴欢迎来一起探讨

© 版权声明

相关文章

暂无评论

none
暂无评论...