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对象
|