Django-api认证

验证过程:每一个中控机有一个key,然后获取到当前时间戳。把key和当前时间戳这两个值进行一次加密,加密之后得到加密的戳,把加密的戳和当前获取的时间戳用管道符分割开生成一个大的字符串(加密戳|时间戳)后,发到服务器端。服务器端也有一个跟中控机一样的key,再把从客户端传过来的时间戳拿来跟key进行一次加密后做比较确定是否一样。但这种方式有漏洞,假如别人在中间获取了你的url之后就会永远向你发数据,所以在这个基础上加了一个超时时间和访问记录做限制。
a. 时间超时
b. 访问记录
c. 加密后进行比较
~~
(1)URL:django_api\django_api\urls.py

from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/', include('api.urls')),  #以api开头转发到api项目里的url
]

(2)URL:django_api\api\urls.py

from django.conf.urls import url,include
from django.contrib import admin
from . import views
urlpatterns = [
    url(r'^asset/', views.asset),
]

(3)视图函数:django_api\api\views.py

#验证了三层:1.时间,2在这个时间以内是否来过,3.反解进行验证
from django.shortcuts import render,HttpResponse
from django.views.decorators.csrf import csrf_exempt,csrf_protect   #关掉csrf
import hashlib
import time
ck = "8kasoimnasodn8687asdfkmasdf"

auth_list=[]                                                #定义空列表(要用缓存服务器做超时时间)

@csrf_exempt                                                #不受csrf保护
def asset(request):                                        #所有请求都封装在request对象里
    # print(request.method)                                 #打印接收什么方式提交
    # print(request.POST)
    # print(request.GET)
    # print(request.body)                                   #POST接收json序列化的数据后
    auth_key_time = request.META['HTTP_AUTHKEY']          #authkey_time是客户端发来的md5+key十六进制数据字符串值+客户端的时间戳的字符串
    auth_key_client,client_ctime = auth_key_time.split('|') #auth_key_client是客户端传md5+key,client_ctime客户端的时间戳的字符串+客户端传的时间戳
    server_current_time = time.time()                       #获取服务器当前时间戳字符串
    if server_current_time-5 > float(client_ctime):       #服务端当前时间戳往后推300秒还大于客户端发过来的时间戳
       return HttpResponse('时间太久远了')                #时间太久远了,直接忽略掉
    if auth_key_time in auth_list:                         #如果authkey_time在列表auth_list说明之前访问过了
       return HttpResponse('你来晚了')
    #如果上面验证成功了下面没成功说明用户自己写了一大堆key
    key_time = "%s|%s" %(ck,client_ctime,)                 #ck:本地的key,客户端传的时间戳
    m = hashlib.md5()
    m.update(bytes(key_time, encoding='utf-8'))            #把md5+key | 当前时间戳加进来
    authkey = m.hexdigest()                                 #生成一个md5+key+当前时间戳的字符串

    if authkey != auth_key_client:                          #如果本地的authkey跟客户端发来的auth_key_client不等于
        return HttpResponse('授权失败')
    auth_list.append(auth_key_time)                         #验证成功的加到访问过的列表auth_list里
    print(auth_list)

    if request.method == 'POST':                                    #如果接收的是POST方式
        import json
        host_info = json.loads(str(request.body,encoding='utf-8'))   #反序列化
        print(host_info)
    return HttpResponse('成功')

启动api后等待客户端发数据:
(1)客户端代码:

import requests
import hashlib                                         #md5
import time
current_time = time.time()                              #当前时间戳
app_id = "8kasoimnasodn8687asdfkmasdf"             #key
app_id_time = "%s|%s" %(app_id,current_time,)          #拼接成:key | 当前时间戳
m = hashlib.md5()                                       #调用hashlib里的md5()生成一个md5的hash对象赋值m
m.update(bytes(app_id_time,encoding='utf-8'))          #用update方法对字符串app_id_time进行md5加密的更新处理
authkey = m.hexdigest()                                 #生成一个md5+key的十六进制数据字符串值

authkey_time = "%s|%s" %(authkey,current_time,)        #authkey_time是md5+key十六进制数据字符串值 | 当前时间戳的字符串
print(authkey_time)

host_data = {                                           #取的主机信息
    'status': True,
    'data':{
        'hostname': 'c1.com',
        'disk': {'status':True,'data': 'xxx'},
        'mem': {'status':True,'data': 'xxx'},
    }
}

response = requests.post(                               #requests模块以post方式把host_data发http请求,response拿到发送后的返回值(http发送后返回的所有的值)
    url='http://127.0.0.1:8080/api/asset/',
    json=host_data,                                     #json把字典序列化成字符串后把host_data请求体POST形式传值到body
    headers={'authkey': authkey_time}                 #请求头headers放验证信息:authkeymd5+key+当前时间戳的字符串,authkey_time是md5+key+当前时间戳的字符串 | 当前时间戳的字符串
)
print(response.text)                                    #打印返回的值

执行客户端后服务端接收数据:
['eb7259b288e686c0ad09e3ab8bdf049e|1554365241.2854595']
{'status': True, 'data': {'hostname': 'c1.com', 'mem': {'status': True, 'data': 'xxx'}, 'disk': {'status': True, 'data': 'xxx'}}}
客户端返回:
eb7259b288e686c0ad09e3ab8bdf049e|1554365241.2854595
成功

posted on 2019-04-04 16:02  我不是西西  阅读(288)  评论(0编辑  收藏  举报