api认证

我们在给别人提供api或者在使用别人的api的时候,往往需要考虑api的调用来自我们授权的或者合法的请求。对于不合法请求我们做相应的处理。

  • 在发送数据的时候。需要做验证:比如说我们授予的合法key。

在推送数据的时候,无论是get还是post数据,在传输的数据的时候需要携带我们指定的key值,推送到后台做验证,在接口方,后台接收到推送数据的时候,

对key值得验证,如果正确的话,后台进行处理,如果不正确,做相应的处理。

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 import tornado.ioloop
 5 import tornado.web
 6 vail_key=['123','231']
 7 
 8 class MainHandler(tornado.web.RequestHandler):
 9     def get(self):
10         rz=self.get_argument('rz')
11         username=self.get_argument('username')
12         print(rz,username)
13         if rz in  vail_key:
14             self.write("Hello, world")
15         else:
16             self.write("permission deny!")
17 
18 application = tornado.web.Application([ #路由系统。
19     (r"/index", MainHandler),
20 ])
21 
22 
23 if __name__ == "__main__":
24     application.listen(8888)
25     tornado.ioloop.IOLoop.instance().start()#让程序建立socket的监听。并处于永远循环中。。。接收客户端请求。

模拟客户端:

1 #!/usr/bin/env python
2 #-*-coding:utf-8-*-
3 # author:liumeide
4 import requests
5 
6 
7 r=requests.get('http://127.0.0.1:8888/index?username=evil&&rz=123',)
8 print(r.text)

 

适用场景:

  • 简单的公司内网之间的接口调用可以这样写。

如上的api认证,有个弊端,因为在传输的过程中被其他人劫持的话,很容抓到我们验证的key值,如果这样的话,一个key可以被很多人使用并发送数据。这样一个接口被多个人利用。

解决劫持和一个key被多个人利用,还需要保持验证key值是需要不断发生变化,防止其他人在劫持的时候,发送相同的加密串。还需要保持在后端验证的时候,一个key值只能使用一次。

总结为:

  • 验证key需要加密、验证key需要不断的发生变化。我们采用时间来和验证的字符串拼接加密、发送的时候将加密的串和被加密的时间串一起发送给后端验证。后端进行相应的解密和验证。
  • 要保持加密的key值只能使用一次,我们可以在后台维护一个列表,当然实际生产中需要写在redis,里面存的是:之前已经请求的验证的key值。我们需要设定一个过期时间,如果不设定过期时间的话。这个列表会越来越大。不易维护。
  • 需要设定的一个超时的时间,比如当前时间和传递过来的时间差不超过20s的时间戳属于合理的请求,反之是非法。这个是防止其他人在劫持我们的验证key时候,而我们的保存加密key的列表已经删除之前的key的值,而导致合法的问题的。
 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 import tornado.ioloop
 5 import tornado.web
 6 import  co
 7 import oc
 8 import hashlib
 9 import time
10 vail_key=['123','321']
11 his_key=[]
12 def md5(x):
13     md=hashlib.md5()
14     md.update(x)
15     return md.hexdigest()
16 
17 
18 class MainHandler(tornado.web.RequestHandler):
19     def get(self):
20         accp_key=self.get_argument('key')
21         sec_key=accp_key.split('|')
22         c_time=sec_key[-1]
23         now_time=time.time()#20秒之后过期。time.time()时间单位为妙。
24         if now_time -float(c_time) <20:#小于20秒时间的请求为合理。
25             if sec_key[0] not  in his_key:#解决api多次使用问题。
26                 for i in vail_key:
27                     i=md5(bytes(c_time+'|'+i,encoding='utf-8'))
28                     if i ==sec_key[0]:
29                         self.write('vali data!')
30                         his_key.append(sec_key[0])
31                         print(accp_key)
32                         return
33                 self.write('permission deny!')
34             else:
35                 self.write('permission deny!')
36         else:
37             self.write('permission deny!')
38 setting={
39     'template_path':'template',#设置模板文件路径。
40     'static_path':'static',#设置静态资源路径
41     'ui_methods':co,
42     'ui_modules':oc,
43 }
44 application = tornado.web.Application([
45     (r"/index", MainHandler),
46 ],**setting)
47 
48 if __name__ == "__main__":
49     application.listen(8888)
50     tornado.ioloop.IOLoop.instance().start()

 

 注意:

  • 如上his_key没有实现过期时间。

客户端:

 1 import  requests
 2 import time
 3 import hashlib
 4 
 5 def md5(x):
 6     md=hashlib.md5()
 7     md.update(x)
 8     return md.hexdigest()
 9 
10 def send_api():
11     time_str=str(time.time())
12     sec_key=time_str+'|'+'123'
13     sec_key=md5(bytes(sec_key,encoding='utf-8'))
14     # send_data=sec_key+"|"+time_str
15     send_data='92c60818a8da7e25d513d87c17acee5c|1478039134.724497'
16     r=requests.get('http://127.0.0.1:8888/index?key=%s'%(send_data))
17     print(r.text)
18 
19 if __name__ == '__main__':
20     send_api()

 

上面的接口认证还存在一个问题:如果劫持这的网络好于合法者,也就是说 劫持者比合法者更快发送加密串的话。就会导致这个问题。在代码级别上无法解决!

posted @ 2016-10-31 21:50  evil_liu  阅读(353)  评论(0)    收藏  举报