API验证
为什么要做API验证?
传输过程中,保证数据不被篡改。
一 静态令牌
客户端
import requests
key = "abcdefg1234567890"
response = requests.get("http://127.0.0.1:8012/api/asset.html",headers={'OpenKey':key})
print(response.text)服务端
api_key = 'abcdefg1234567890' # 可以放置在配置文件中
def asset(request):
if request.method == 'GET':
client_key = request.META.get('HTTP_OPENKEY') # 规则HTTP_大写的key
if client_key == api_key:
return HttpResponse('验证通过')
else:
return HttpResponse('验证失败')总结:存在隐患,key值一旦被他人截取,则可验证成功
二 简易动态令牌
根据当前时间来生成动态令牌
客户端
import time
import hashlib
# 通过时间组成动态字符串
key = "abcdefg1234567890"
ctime = time.time()
new_key = '%s|%s' %(key,ctime)
m = hashlib.md5()
m.update(bytes(new_key,encoding='utf8'))
md5_key = m.hexdigest()
md5_time_key = '%s|%s' %(md5_key,ctime)
response = requests.get("http://127.0.0.1:8012/api/asset.html",headers={'OpenKey':md5_time_key})
print(response.text)服务端
from django.shortcuts import render,HttpResponse
import hashlib
api_key = 'abcdefg1234567890' # 可以放置在配置文件中
def asset(request):
if request.method == 'GET':
client_md5_time_key = request.META.get('HTTP_OPENKEY') # 规则:HTTP_大写的key
client_md5_key,client_time = client_md5_time_key.split('|')
server_new_key = '%s|%s' % (api_key, client_time)
m = hashlib.md5()
m.update(bytes(server_new_key, encoding='utf8'))
server_md5_key = m.hexdigest()
if client_md5_key == server_md5_key:
return HttpResponse('验证通过')
else:
return HttpResponse('验证失败')总结:存在隐患,md5_time_key一旦被他人截取,则可验证成功
三 真正的动态令牌
思路:还是通过时间来达到动态效果,但要满足以下几点:
- 服务端时间与客户端发送过来的时间与做比较,超时则不允许访问,比如30s
- 服务端server_md5_key与客户端client_md5_key对比,不匹配则验证失败
- 在服务端建立一个已访问key数据列表或字典,验证客户端发送过来的key是否存在,若存在则证明已经访问过,则不允许访问
客户端
import requests
import time
import hashlib
# 通过时间组成动态字符串
key = "abcdefg1234567890"
ctime = time.time()
new_key = '%s|%s' %(key,ctime)
m = hashlib.md5()
m.update(bytes(new_key,encoding='utf8'))
md5_key = m.hexdigest()
md5_time_key = '%s|%s' %(md5_key,ctime)
response = requests.get("http://127.0.0.1:8012/api/asset.html",headers={'OpenKey':md5_time_key})
print(response.text)服务端
from django.shortcuts import render,HttpResponse
import hashlib
import time
timeout = 30 # 设置超时时间,可以放置在配置文件中
api_key = 'abcdefg1234567890' # 可以放置在配置文件中
api_key_record = {
# '21ca6c1170cba56ae8fc0dfa9e75ab2d|1522419311.9073045':1522419341.9073045
} # 初始化存储客服端key字典
def asset(request):
if request.method == 'GET':
client_md5_time_key = request.META.get('HTTP_OPENKEY') # 规则:HTTP_大写的key
client_md5_key,client_time = client_md5_time_key.split('|')
client_time = float(client_time)
server_time = time.time()
# 第一层验证--超时验证
if server_time - client_time > timeout:
return HttpResponse('超时,验证失败...')
# 第二层验证--数据一致性验证
server_new_key = '%s|%s' % (api_key, client_time)
m = hashlib.md5()
m.update(bytes(server_new_key, encoding='utf8'))
server_md5_key = m.hexdigest()
if client_md5_key != server_md5_key:
return HttpResponse('修改数据,验证失败...')
# 删除超时数据
for k in list(api_key_record.keys()):
v = api_key_record[k]
if server_time > v:
del api_key_record[k]
# 第三层验证--用户验证
if client_md5_time_key in api_key_record:
return HttpResponse('有用户已登录,验证失败...')
else:
api_key_record[client_md5_time_key] = client_time + timeout
return HttpResponse('验证通过')
总结:该方式借鉴了Tornado加密Cookie类似(创建动态key:md5(key+tiem)|tiem)。
四 补充
以上还存在一个风险,那就是人家的网速比我们快,获取到我们发送的数据然后在我们之前发送到服务端,该如何处理呢?
- 可搭建内网
- 数据加密(具体请参考:加密解密--RSA&AES)

浙公网安备 33010602011771号