验证机制:利用tornado源码的签名cookie原理
前景:
比如现在有个请求数据的过程,PC1要去Srv1去获取数据,但是在获取的过程当中被第三人所截获这样就使得我们的请求格式等数据泄漏,第三方他人也可以模拟一样的请求来获取数据,那么,如果这个请求是post呢?!这样可能就会造成数据泄漏大损失或者说直接服务器瘫痪
所以我们需要做api验证,来确保数据的安全性
我的的api验证分三步:
一、唯一标识
python模拟请求:
import request
request.get("http://127.0.0.1/test.html",headers={'auth-api':"sdafasdf"})
我的headers中的auth-api可以是任意唯一的一个字符串,这就是别人不知道的
这里需要注意:
1、headers中的键必须是小写且-分割,不可以是_,如果是_,则在服务端接收不到
2、服务器接收请求,会将auth-api解析成HTTP_AUTH_API 字母变大写,-变_,并且开头加了个HTTP_
服务端取值:
request.META.get('HTTP_AUTH_API')
缺点:
如果是这样的,那么第三方他人可以看出我的auth-api的唯一字符串,也就是说这也是不安全的,毕竟还可以找到规律
二、验证动态的唯一标识(在第一步的基础上)
2.1(动态唯一标识):
我可以利用时间戳以及唯一标识进行hash出一个新的动态唯一标识。
import time,hashlib
def md5(arg):
hs = hashlib.md5()
hs.update(arg.encode('utf-8'))
return hs.hexdigest()
key = "asdfasgdsf"
ctime = str(time.time()) # 12451.123
new_key = %s|%s %(key,ctime) # asdfasgdsf|时间戳
md5_str = md5(new_key) # 唯一标识:sadfklgasdg
api_header_val = %s|%s %(md5_str,ctime) # sadfklgasdg|时间戳
request.get("http://127.0.0.1/test.html",headers={'auth-api':api_header_val})
原理:
请求时,请求头里带着动态的唯一表示已经所生成这个动态唯一表示的时间戳字符串,
这样我的客户端跟服务端都有别人不知道的唯一字符串标识,我的客户端都可以根据这个时间戳生成动态的唯一标识
而黑客他人并没有我的这个唯一标识,光有时间戳是没有用的
缺点:
黑客还是可以拿到动态的这个唯一标识,依然可以模拟请求,不光如此,这样的话可以被利用的唯一标识更多了,所以需要做时间或者次数的限制,请看下文
2.2(添加时间限制):
理论:
在2.1的基础上实现:
a.在服务器上也获取一下当时的时间戳,然后将请求来的时间戳转为float
b.将请求来的float时间戳+10(也就是我允许放行的时间在10秒内的),判断是否小于当前的时间戳,如果+10还小,那么当然就是过期的了,如果真的网速那么慢,认命吧
有个牛逼的地方,在这一步,黑客可以通过修改时间来通过我的时间上的认证,但是,你是不是忘记了我的认证规则呢?
对,没错,我的认证是通过唯一标识跟时间戳hash的,也就是说你改任意一个地方就肯定过不了我的动态唯一认证。哈哈哈,认命吧
好了,现在想想这样是不是就能保证我的数据安全了呢?
答案当然是否定的,如果这样就完了我后边还写那么多干嘛,写这个真的很累的呢。
缺点:
我定义的时间间隔为10秒,如果黑客特么单身30年的呢,手速是个关键,他真的在10秒内完成了模拟请求呢?结果当然是我没办法了
2.3(添加次数限制)
在2.2的基础上做一层次数验证的限制
比如我在服务端写个列表,所有的请求进来后我会记录一下这次的动态唯一标识,那么即使黑客有了我的唯一标识,也在10秒内再次模拟请求
那么我已经在我的记录列表里存下了真实的请求唯一标识,黑客的记录来了,也就是这个唯一标识是第二次了
这时,我就会判断,我的列表里是否已经存在了这个唯一标识,如果有,那么我就断定这个请求是非法的。
注意:
无论是列表记录还是字典记录或者其他,都会有个时间上的处理,根据2.2的时间定,如果过了这个时间,那么就会自动清除本条记录
因为在判断次数之前已经有了时间的判断。这样就会保证这个列表或字典不会因为数据量太大而造成的空间浪费
总结:
1、在某一个请求来到我的服务端时,我首先会在headers里找到HTTP_AUTH_API的值,并根据服务端跟客户端提前定义好的唯一字符串以及传过来的时间戳进行hash
2、在hash后得到的动态唯一标识后,进行验证,验证有3步(
①判断hash后的唯一标识是否与请求中的唯一标识一致
②判断请求时间是否在某时间段内(比如10秒)
③判断是否为第一次请求(也就是服务端是否已经存在这个唯一标识)
)
3、响应