python API验证
API验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
API验证: a. 发令牌: 静态 PS: 隐患 key被别人获取 b. 动态令牌 PS: (问题越严重)用户生成的每个令牌被黑客获取到,都会破解 c. 高级版本 PS: 黑客网速快,会窃取, so要对数据加密 d. 终极版本 特点: 为什么要用API ? - 数据在传输过程中,保证数据安全 你是如何设计的 ? - Tornado 中的加密Cookie类似 - 创建动态key md5(key + time)|time (Tornado中也是这么做) - 限制 - 第一关: 时间 - 第二关: 算法规则 - 第三关: 已访问的记录 PS: 黑客网速快,会窃取, so要对数据加密 |
a. 客户端和服务端都有一个相同的key
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
客户端把key发给服务端,服务端拿着自己的key和客户端的key做比较 ###客户端 import time import requests key = "asdfasdfasdfasdf098712sdfs" response = requests.get( "http://127.0.0.1:8000/api/asset.html" ,headers = { 'OpenKey' :key}) print (response.text) ###服务端 #print(request.META) key = request.META.get( "HTTP_OPENKEY" ) if key ! = settings.AUTH_KEY: return HttpResponse( "验证失败" ) |
b. key和时间
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
#客户端和服务端都有一个相同的key #客户端把加密key和当前时间发给服务端,服务端收到后把客户端发来的时间和自己的key加密 #然后把加密后的字串和客户端的字串比较 #客户端 import time import requests import hashlib ctime = time.time() key = "asdfasdfasdfasdf098712sdfs" new_key = "%s|%s" % (key,ctime,) m = hashlib.md5() m.update(bytes(new_key,encoding = 'utf-8' )) #里面是字节数据 md5_key = m.hexdigest() #返回值是字符窜类型 md5_time_key = "%s|%s" % (md5_key,ctime) response = requests.get( "http://127.0.0.1:8000/api/asset.html" ,headers = { 'OpenKey' :md5_time_key}) print (response.text) #服务端 client_md5_time_key = request.META.get( "HTTP_OPENKEY" ) client_md5_key,client_ctime = client_md5_time_key.split( "|" ) temp = "%s|%s" % (settings.AUTH_KEY,client_ctime) m = hashlib.md5() m.update(bytes(temp, encoding = 'utf-8' )) server_md5_key = m.hexdigest() if server_md5_key ! = client_md5_key: return HttpResponse( "验证失败" ) |
c. 高级版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
#客户端和服务端都有一个相同的key #客户端把加密key和当前时间发给服务端 #服务端验证: #1)服务端判断服务器当前的时间是否比客户端时间快10s,如果在10s内通过,有效的杜绝了案例二成千上万的key #2)服务器获取客户端时间和自己key加密然后和 客户端获取到的key比较 #3)删除与现在时间相差10s的数据(之后用memcache,redis) #3)在字典里判断是否有这个key,如果有不通过,没有加入字典(之后用memcache,redis) #客户端 import time import requests import hashlib ctime = time.time() key = "asdfasdfasdfasdf098712sdfs" new_key = "%s|%s" % (key,ctime,) m = hashlib.md5() m.update(bytes(new_key,encoding = 'utf-8' )) #里面是字节数据 md5_key = m.hexdigest() #返回值是字符窜类型 md5_time_key = "%s|%s" % (md5_key,ctime) print (md5_time_key) response = requests.get( "http://127.0.0.1:8000/api/asset.html" ,headers = { 'OpenKey' :md5_time_key}) #黑客获取调用 #response = requests.get("http://127.0.0.1:8000/api/asset.html",headers={'OpenKey':"f610077a7001c53b5a74868c5544b388|1501514254.455578"}) print (response.text) #服务端 api_key_record = { "76942d662d98ebe3b920a7b791bf5040|1501510243.92804" : 1501510243.92804 , } def asset(request): client_md5_time_key = request.META.get( "HTTP_OPENKEY" ) client_md5_key,client_ctime = client_md5_time_key.split( "|" ) client_ctime = float (client_ctime) server_ctime = time.time() #第一关 时间关 if server_ctime - client_ctime > 10 : return HttpResponse( "第一关 小伙子,别虎我,太长了" ) #第二关 客户端时间和服务端key加密和 客户端的密钥对比 temp = "%s|%s" % (settings.AUTH_KEY,client_ctime) m = hashlib.md5() m.update(bytes(temp, encoding = 'utf-8' )) server_md5_key = m.hexdigest() if server_md5_key ! = client_md5_key: return HttpResponse( "第二关 规则正确" ) #以后基于memcache,目前先写入内存删除超过10s的值 for k in list (api_key_record.keys()): v = api_key_record[k] if server_ctime > v: del api_key_record[k] #第三关 判断字典里是否有之前访问的key,如果有不通过,没有加入字典 if client_md5_time_key in api_key_record: return HttpResponse( "第三关 已经有人来过了" ) else : api_key_record[client_md5_time_key] = client_ctime + 10 |
d. 终极版本
1
2
3
|
注意: key 是从配置文件获取的 装饰器要返回Httpresponse对象 |