API验证

22 篇文章 3 订阅
2 篇文章 0 订阅

API验证

在web应用中,服务端提供的API接口必须有某种安全机制,来识别Http请求是否合法,以防别有用心之人截获http请求,对服务端进行攻击的行为。这里,参考Tornado签名cookie源码,来实现一个API验证的功能。

基本思路:

  1. 服务端给有权限访问的客户端发放key,客户端每次访问时携带key给服务端进行验证。
  2. 为了防止请求被截获后key泄露,将key与当前时间进行加密后生成动态密钥。
  3. 请求被截获后,不法分子依然能够直接使用这个动态密钥通过服务端的验证。因此服务端增加有效期验证,比如5S超时,超过这个时间的请求无法通过验证。
  4. 如果不法分子截获请求,并在超时前访问API,还是有风险。因此服务端增加第一次访问验证,同样密钥如果是第二次请求,无法通过。


下面我们在Django中实践一下:

  1. 新建项目API_AUTH,创建应用app01,定义路由如下:

    from django.conf.urls import url
    from app01 import views
    
    urlpatterns = [
        url(r'^api_auth/$', views.api_auth),
    ]


  1. 写一个脚本test.py,通过request模块对上述路由发起Http请求

    import requests, time, hashlib
    
    key = 'asdgasgewfqsef'
    url = 'http://127.0.0.1:8000/server.html'
    
    
    # 将key与当前时间加密生成动态密钥token
    
    timestamp = time.time()
    temp = '{key}|{time}'.format(key=key,time=timestamp)
    md5_str = hashlib.md5(temp.encode('utf-8')).hexdigest() 
    token = '{md5_str}|{time}'.format(md5_str=md5_str, time=timestamp)
    
    
    # 在Http请求头中携带token
    
    response = requests.get(url, headers={"auth-key": token})
    print(response.text)
    
    
    # 模拟超时发送请求
    
    fake = token
    time.sleep(6)
    response = requests.get(url, headers={'auth-key': fake})
    print('second...',response.text)

    说明:

    1. 通过headers={key: value}发送自定义请求头


  1. 服务端api_auth视图函数:

    def api_auth(request, *args, **kwargs):
    
        key = 'asdgasgewfqsef' # 服务端与客户端持有同样的key
        temp_key = {
            # client_md5: timestamp  --> 过期自动清除, 判断是第一次请求
            # 通过redis,Memcache来做过期自动清除
        }
    
        token = request.META.get('HTTP_AUTH_KEY')  # 提取请求头中的密钥
        print('token...',token)
        # 6e632f8e858e07ffcc3b636a1577121b|1506983215.7659595
        # 分割出客户端动态key和时间字符串
        client_md5 = token.split('|')[0]
        timestamp = token.split('|')[1]
    
        # 用客户端的时间字符串和服务端的key,生成服务端动态key
        temp = '{key}|{time}'.format(key=key, time=timestamp)
        server_md5 = hashlib.md5(temp.encode('utf-8')).hexdigest()
    
        now = time.time()
        if float(timestamp) + 5 < now:  # 5s过期验证
            return HttpResponse('呵呵')
    
        elif server_md5 != client_md5:  # 动态key验证
            return HttpResponse('呵呵')
    
        elif temp_key[client_md5]:  # 第一次访问验证
            return  HttpResponse('呵呵')
    
        else:  # 验证通过,将这次的请求的动态key和时间戳作为记录保存,以作下次第一次访问验证。
            temp_key[client_md5] = timestamp  
            return HttpResponse('验证通过')

    说明:

    1. 自定义请求头的信息从request.META中获取;
    2. 请求头中的'auth-key'会被转化为HTTP_AUTH_KEY
    3. temp_key中的记录后期通过redis,Memcache来做过期自动清除, 参考AES加密


  1. 封装成装饰器,可以给需要的视图函数使用

    def api_auth(func):
        def deco(request, *args, **kwargs):
            key = 'asdgasgewfqsef' # 服务端与客户端持有同样的key
            # 同上......
            now = time.time()
            if float(timestamp) + 5 < now:  # 5s过期验证
                return HttpResponse('呵呵')
            elif server_md5 != client_md5:  # 动态key验证
                return HttpResponse('呵呵')
            elif temp_key[client_md5]:  # 第一次访问验证
                return  HttpResponse('呵呵')
            else:  # 验证通过,将这次的请求的动态key和时间戳作为记录保存,以作下次第一次访问验证。
                temp_key[client_md5] = timestamp
                return func(request, *args, **kwargs)
    
        return deco
    
    @api_auth
    def view_func():
        pass
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值