1.1 api认证原理介绍

  1、api认证原理:客户端生成秘钥

      1) 客户端与服务器端有一个相同的字符串作为auth_key
      2) 客户端使用encryption="auth_key|time.time()"用auth_key和客户端时间生成md5秘钥
      3) 客户端将"encryption|time.time()" 将生成的秘钥和发送请求的时间一起发送给服务器

  2、api认证原理:服务器验证秘钥三步曲

      1、时间验证: 如果请求到达服务器端时间距离客户端发送请求的时间大于2秒,验证失败
      2、是否存在: 这个秘钥第一次过来时会加入列表中,如果已经在列表中证明已经来过,验证失败
      3、秘钥正确: 只有前两关都通过,在通过服务器的auth_key与客户端发送的时间生成秘钥看是否相等

 1.2 api认证插件使用

  1、测试API认证插件步骤

      1、创建任意django项目,如ApiAuth,无需指定静态文件等,只需创建app01
      2、在app01中使用CBV创建AssetView视图函数处理get和post请求,并重写dispatch方法,不使用csrf规则
      3、在app01同级目录下创建utils目录,并创建认证文件auth.py
      4、在AssetView的get和post函数中使用自己定义的@method_decorator(auth.api_auth)进行api认证
      5、客户端访问时只用使用服务器端指定的字符串,和发送请求的时间生成秘钥,验证通过才能访问

  2、测试代码

import time
import hashlib
from django.http import JsonResponse

ASSET_AUTH_KEY = '299095cc-1330-11e5-b06a-a45e60bec08b'
ASSET_AUTH_HEADER_NAME = 'HTTP_AUTH_KEY'
ASSET_AUTH_TIME = 2

ENCRYPT_LIST = [
    # {'time': 1516180308.850576, 'encrypt': '25bd4a6454329e7633b4db5c810c44ac'}
]


def api_auth_method(request):
    # 获取客户端header中传入的验证字符串:{'auth-key': '7b01e466ca23c9a3fb8c3a12b0214635|1516179535.832950'}
    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                      # encrypt = 客户端发送时间 + 授权字符串  的md5值
                                                 # timestamp 是客户端发送的时间
    timestamp = float(timestamp)
    limit_timestamp = time.time() - ASSET_AUTH_TIME

    if limit_timestamp > timestamp:             # 如果当前时间比请求时间的差大于2 秒(验证失败)
        return False
    ha = hashlib.md5(ASSET_AUTH_KEY.encode('utf-8'))
    # 授权字符串 + 客户端发送请求那一刻时间   的md5值与客户端发送的值是否相等
    ha.update(bytes("%s|%f" % (ASSET_AUTH_KEY, timestamp), encoding='utf-8'))
    result = ha.hexdigest()
    if encrypt != result:
        return False

    exist = False
    del_keys = []
    for k, v in enumerate(ENCRYPT_LIST):
        # v = {'time': 1516180308.850576, 'encrypt': '25bd4a6454329e7633b4db5c810c44ac'}
        m = v['time']
        n = v['encrypt']
        if m < limit_timestamp:     # 时间已过期
            del_keys.append(k)      # 将ENCRYPT_LIST列表中对应要删除的索引加入到del_keys列表中
            continue
        if n == encrypt:
            exist = True
    for k in reversed(del_keys):              # 将ENCRYPT_LIST列表中已到的秘钥删除
        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):      # 调用api_auth_method方法验证客户端秘钥是否有效
            return JsonResponse({'code': 1001, 'message': 'API授权失败'}, json_dumps_params={'ensure_ascii': False})
        return func(request, *args, **kwargs)

    return inner
Project/utils/auth.py 用于api认证的装饰器(插件代码)

相关文章:

  • 2021-08-22
  • 2022-02-14
  • 2022-01-07
  • 2021-07-28
  • 2022-01-05
  • 2021-06-11
  • 2022-02-03
猜你喜欢
  • 2021-12-16
  • 2021-07-25
  • 2022-01-25
  • 2022-12-23
  • 2021-09-22
  • 2021-07-21
  • 2021-11-26
相关资源
相似解决方案