码迷,mamicode.com
首页 > Windows程序 > 详细

API验证策略

时间:2018-08-05 23:27:38      阅读:333      评论:0      收藏:0      [点我收藏+]

标签:api   过期   xxx   col   lis   字符   字典   UNC   设置   

第一步  携带key的请求

  客户端发送http请求访问API时,在请求头里设置一个双方约定好的key, 其实没有什么卵用,请求头很容易抓包抓到

在请求头中设定key的时候,不能在key值中插入‘_’,因为django不识别‘_’,所以只能用‘-’来替代下划线,比如,客户端 的请求头‘auth-api‘:xxxxxx会被服务端自动转换成 ‘HTTP_AUTH_API‘:xxxxxxx格式

在服务器中获取使用clent_key=request.META.get(‘HTTP_AUTH_API‘)

客户端

import  requests
key=sssdkjrjefjewfakfhkj
respose=requests.get(url=http://127.0.0.1:8000/test.html/,headers={auth-api:key}).text
#如果给Django程序发送请求头,如果headers里面的内容使用下滑杠 _,Django会不认识;
#auth-api  -----> 转换成 HTTP_AUTH_API格式
#服务端获取clent_key=request.META.get(HTTP_AUTH_API)
print(respose)

服务器

def test(request):
    key=sssdkjrjefjewfakfhkj
    clent_key=request.META.get(HTTP_AUTH_API)
    if clent_key == key:
        return HttpResponse(你得到我了)
    else:
        return HttpResponse(休想)

这种策略不具备动态性,很容易被抓包抓到,黑客们只需要带着你的url再发一次就好了,所以我们先引出第二部,发送动态的url

第二步  携带key的动态url请求

首先来考虑如何实现动态性,不管是你的用户名还是密码,还有约定好的key值都不可能去动态改变,那剩下的也就只有时间戳了,很多时候我们都利用时间戳的唯一性去定制一些东西。

如果我们把key+时间戳合并再进行MD5加密成aaaaaaaa,再携带时间戳,以aaaaa|时间戳的形式放在请求头传递

服务器端我们先把摘取到时间戳,然后对key+时间进行MD5加密,然后和传递来的密文进行比对。

这样一来,好像还是毫无卵用,依然可以被获取到。。。

客户端

import  requests
import time
import hashlib
key=sssdkjrjefjewfakfhkj
ctime=str(time.time())
def MD5(arg):
    hs=hashlib.md5()
    hs.update(arg.encode(utf-8))  #python3加密使用字节类型
    return hs.hexdigest()


new_key=%s|%s % (key,ctime)  # sssdkjrjefjewfakfhkj | 时间戳
md5_str=MD5(new_key)
auth_api_val=%s|%s%(md5_str,ctime)  #d0e0ca7d1f8f72d60715696d4baac3b2(key和时间戳加密后的结果)| 时间戳
print(md5_str)
respose=requests.get(url=http://127.0.0.1:8000/test.html/,headers={auth-api:auth_api_val}).text
print(respose)

  服务端

import hashlib
import time

def MD5(arg):
    hs = hashlib.md5()
    hs.update(arg.encode(utf-8))  # python3加密使用字节类型
    return hs.hexdigest()

def test(request):
    key=sssdkjrjefjewfakfhkj
    auth_api_val=request.META.get(HTTP_AUTH_API)  #052dd27c130f4b9b5a8a4ec4b243962d | 1507374976.4620001
    client_md5_str,client_ctime =auth_api_val.split(|,maxsplit=1)
    server_md5_str=MD5(%s|%s%(key,client_ctime))

    if client_md5_str== server_md5_str:
        return HttpResponse(你得到我了)
    else:
        return HttpResponse(休想)

第三步  过滤掉已经访问的url

  仔细一想我们的动态url已经具备了唯一性,任凭黑客多么牛逼也不可能反解MD5值拿到key值,所以我们只需要记录一下已经访问过的url。

  即使不幸被黑客获取到url,也没关系,因为他拿到的url已经被我们记录过了,变成一次性的啦。

  但是如果访问量非常大的话,我们在后台维护的表单太过于庞大了,所以我们提出第四种方案来解决这个问题。

第四步 最终幻想

  现在存在的问题只有数据库过于庞大的问题,如果我们可以定期清理数据库那不就好了嘛。

  因此我们可以设计一个expire_time,也就是有效时间,其实越短越好,因为正常每次用户访问都是一个唯一的url

  我们取到最近客户端发来的时间戳,然后减去有效时间,如果没有过期的话允许访问,已经过期的话,则拒绝。

  至于删除表格数据可以设定一个可以长一点的周期,避免因监控表单而带来的性能损耗

  客户端

import  requests
import time
import hashlib
key=sssdkjrjefjewfakfhkj
ctime=str(time.time())
def MD5(arg):
    hs=hashlib.md5()
    hs.update(arg.encode(utf-8))  #python3加密使用字节类型
    return hs.hexdigest()

new_key=%s|%s % (key,ctime)  # sssdkjrjefjewfakfhkj | 时间戳
md5_str=MD5(new_key)
auth_api_val=%s|%s%(md5_str,ctime)  #d0e0ca7d1f8f72d60715696d4baac3b2(key和时间戳加密后的结果)| 时间戳
print(md5_str)
respose=requests.get(url=http://127.0.0.1:8000/test.html/,headers={auth-api:auth_api_val}).text
print(respose)

  服务端

#api验证装饰器
def api_auth(func):
    def inner(request,*args,**kwargs):
        server_float_ctime = time.time()
        key = sssdkjrjefjewfakfhkj
        auth_api_val = request.META.get(HTTP_AUTH_API)  # 052dd27c130f4b9b5a8a4ec4b243962d | 1507374976.4620001
        client_md5_str, client_ctime = auth_api_val.split(|, maxsplit=1)
        client_float_ctime = float(client_ctime)
        # 第1关时间限制
        if client_float_ctime + 5 < server_float_ctime:
            return HttpResponse(想要破解密码最在5秒之内)
        # 第二关 MD5加密
        server_md5_str = MD5(%s|%s % (key, client_ctime))
        if client_md5_str != server_md5_str:
            return HttpResponse(休想)
        # 第三关
        for k in list(visited_keys.keys()): #清空字典访问记录
            v=visited_keys[k]
            if server_float_ctime > v:
                del visited_keys[k]
        #已经使用过 MD5加密字符串(访问记录)
        if visited_keys.get(client_md5_str):
            return HttpResponse(你放弃吧)
        visited_keys[client_md5_str] = client_float_ctime+5#(只需维护5秒之内访问记录即可,因为超过5秒第一关都过不去了)
        return func(request,*args,**kwargs)
    return inner

 

API验证策略

标签:api   过期   xxx   col   lis   字符   字典   UNC   设置   

原文地址:https://www.cnblogs.com/yangziyao/p/9427713.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!