Python API简单验证

Posted Dandy Zhang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python API简单验证相关的知识,希望对你有一定的参考价值。

前言

因为CMDB内部的需求,需要一个API进行数据传输,用来传递需要抓取的服务端信息信息给抓取的autoclient,autoclient抓取好之后再通过API传输到服务器,保存到数据库。但是为了防止恶意的API访问,需要做一个验证。

 

设想一

可以在客户端跟服务端都规定好一串随机字符串做验证,只有当带着这串验证的请求发送过来的时候,才让其进行访问。

如果学过了爬虫,大家很容易就发现,这串随机字符串在浏览器里面是可以监听的,多观察几次总是会发现的。而且无论通过如何的方式,只要暴露在外面,都是会被察觉的。此时,就需要对其进行加密。

 

设想二

既然随机字符串在web传输中是明文状态,那我们试着将其转换成密文的,转换下思路,如果每次的请求都是随机字符串配合一串一直变动的值进行md5加密,此时,产生的验证字符串也应该变成动态密文。用什么做动态字符串来配合约定好的字符串进行md5加密呢?既然是动态的,时间戳,是最好的选择。   

此时一切看着都很完美,但是,忽略了一点,无论是不是加密的字符串,http请求的时候都是可以监听到的,所以即使加密,即使不知道怎么加密的,依旧可以直接拿着这串字符串直接进行验证访问。尴尬。。。

 

设想三

其实上面的设想二已经做到了动态,思路上只要改一点就立刻变成可行的了。在http请求的时候,即使是在相当糟糕的网络环境里,也不会需要发送非常长的时间,因此,卡住时间便可以实现。

在拿到client的时间戳是,服务器段只需要跟当前时间戳进行比对,如果时间间隔小于10秒就当作正常访问。就可以了。

上面的设计思路完美的解决了动态的问题,此时不免还有疑问,如果真的会在10s内盗取到字符串直接访问呢?

 

完善思路

基于上面的问题,可以再多加异步验证,写一个列表,访问过的字符串都放在列表里,后面的访问都跟此列表比对下,如果在此列表内,就拒绝访问。

如上的设计思路就可以解决问题。

优化

最后的设计思路肯定能解决问题,但是也存在一个问题,就是,随着时间进度的推移,访问列表一定会越来越大,始终是不友好的一点。肯定需要给字符串设计一个超时时间。

visited_list = [\'28g12b12128912e2kj|127381237812391\', \'829312g12be120e102ej12je91|12312984123123\',....]

如果以上述的方式取跟系统时间比较当然是一件很费事的工作,占用很多的IO,可以使用redis来轻松实现这个功能。

 

 

 

 CBV通过此类装饰方式实现验证

 验证代码

def api_auth_method(request):
    auth_key = request.META.get(\'HTTP_AUTH_KEY\')
    if not auth_key:
        return False
    sp = auth_key.split(\'|\')
    if len(sp) != 2:
        return False
    encrypt, timestamp = sp
    timestamp = float(timestamp)
    limit_timestamp = time.time() - ASSET_AUTH_TIME
    print(limit_timestamp, timestamp)
    if limit_timestamp > timestamp:
        return False
    ha = hashlib.md5(ASSET_AUTH_KEY.encode(\'utf-8\'))
    ha.update(bytes("%s|%f" % (ASSET_AUTH_KEY, timestamp), encoding=\'utf-8\'))
    result = ha.hexdigest()
    print(result, encrypt)
    if encrypt != result:
        return False

    exist = False
    del_keys = []
    for k, v in enumerate(ENCRYPT_LIST):
        print(k, v)
        m = v[\'time\']
        n = v[\'encrypt\']
        if m < limit_timestamp:
            del_keys.append(k)
            continue
        if n == encrypt:
            exist = True
    for k in del_keys:
        del ENCRYPT_LIST[k]

    if exist:
        return False
    ENCRYPT_LIST.append({\'encrypt\': encrypt, \'time\': timestamp})
    return True


def api_auth(func):
    def inner(request, *args, **kwargs):
        if not api_auth_method(request):
            return JsonResponse({\'code\': 1001, \'message\': \'API授权失败\'}, json_dumps_params={\'ensure_ascii\': False})
        return func(request, *args, **kwargs)

    return inner
auth

 

以上是关于Python API简单验证的主要内容,如果未能解决你的问题,请参考以下文章

教程4 - 验证和权限

爬虫遇到头疼的验证码?Python实战讲解弹窗处理和验证码识别

python 用于在终端中运行的sublime text 3的简单代码片段制作工具

Android SMS Verification API 结果码始终为 0

验证码识别与生成类API调用的代码示例合集:六位图片验证码生成四位图片验证码生成简单验证码识别等

使用 Python 进行 Spotify API 身份验证