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()
上面的接口认证还存在一个问题:如果劫持这的网络好于合法者,也就是说 劫持者比合法者更快发送加密串的话。就会导致这个问题。在代码级别上无法解决!
学习是一种态度,坚持是质变的利器!

浙公网安备 33010602011771号