基于Tornado签名cookie源码设计API认证

想法1

服务端客户端个保存相同的一串字符串,客户端发送API请求时带着这段字符串来我服务端做校验,通过则返回相应数据,否则拒绝访问

弊端

黑客截取到请求信息,可直接会获取到该字符串,想服务端发送请求并能获取到数据,安全性太低

想法2

设置动态的随机验证码,那么字符串我们不变,利用时间的动态性,我们将固定的字符串加上当前请求时间,利用md5加密算法生成随机验证码,那么我们在发送数据的时候,除了要发生成的随机验证码外,还要将当前请求的时间也一并发给服务端,这样服务端才可以利用客户端发来的时间和实现存好的校验字符串凭借加密在对比客服端的来判断是否相同,

优点

1.时间限制

2.加密规则限制(字符串不能被修改)

弊端

看似完美,但是暴露出来的问题也是致命的,相当于你每产生一个验证码只要被黑客截取到,那都是有效的,也就是说随着项目运行时间的增加,黑客手里拿到能访问你API接口的认证字符串都可以拿去卖钱了

想法3

在上面的基础上在加上一条过期时间的限制,也就是当用户第一次来访问时,将验证字符串和对应的时间作为键值存储起来并且设置超时时间(这个可以放入Redis或MongoDB中,因为他们在设置键值时可以给这个键值对设置超时时间,超时自动清除)

优点

设置了三道关卡来校验用户的合法性

小Bug

黑客的网速比你快很多,你在发送的途中,黑客截取了并先你一步发送成功,那么你就变成了非法用户了,当然这种情况发生的概率是很小的,。

处理办法

将你发送的整个数据都进行加密,那么就算黑客拿到你的数据并比你快一步提交了,那么相当于在帮你提交数据,

具体了解猛击这里

import requests
import time
import hashlib




def md5(arg):
    hs = hashlib.md5()
    hs.update(arg.encode('utf-8'))
    return hs.hexdigest()

key = "asdfuasodijfoausfnasdf"
ctime = str(time.time())
new_key = "%s|%s" %(key,ctime,) # asdfuasodijfoausfnasdf|时间戳
md5_str = md5(new_key)
# 6f800b6a11d3f9c08c77ef8f77b2d460,  # asdfuasodijfoausfnasdf|时间戳
auth_header_val = "%s|%s" %(md5_str,ctime,) # 6f800b6a11d3f9c08c77ef8f77b2d460|时间戳
print(auth_header_val)




response = requests.get('http://127.0.0.1:8000/api/test.html',headers={'auth-api':auth_header_val})
print(response.text)
客户端代码
import hashlib
import time
def md5(arg):
    hs = hashlib.md5()
    hs.update(arg.encode('utf-8'))
    return hs.hexdigest()

key = "asdfuasodijfoausfnasdf"
# redis,Memcache
visited_keys = {
    # "841770f74ef3b7867d90be37c5b4adfc":时间,  10
}

def api_auth(func):
    def inner(request,*args,**kwargs):
        server_float_ctime = time.time()
        auth_header_val = request.META.get('HTTP_AUTH_API')
        # 841770f74ef3b7867d90be37c5b4adfc|1506571253.9937866
        client_md5_str, client_ctime = auth_header_val.split('|', maxsplit=1)
        client_float_ctime = float(client_ctime)

        # 第一关
        if (client_float_ctime + 20) < server_float_ctime:
            return HttpResponse('时间太久了,再去买一个吧')

        # 第二关:
        server_md5_str = md5("%s|%s" % (key, client_ctime,))
        if server_md5_str != client_md5_str:
            return HttpResponse('休想')

        # 第三关:
        if visited_keys.get(client_md5_str):
            return HttpResponse('你放弃吧,来晚了')

        visited_keys[client_md5_str] = client_float_ctime
        return func(request,*args,**kwargs)

    return inner


@api_auth
def test(request):
    return HttpResponse('正常用户')
服务端代码

服务端将我们API验证的代码块写成装饰器的形式~~~

 

posted @ 2018-08-06 22:52  JasonJi  阅读(305)  评论(0编辑  收藏  举报