之前需要在两台服务器之间频繁传输一些重要数据,一台服务器开放数据接口,另一台调用,为了防止数据泄露,所以简单构思了一下,在接口上添加了一个简单的token验证机制,采用时间戳、base64和密码表来完成,为对称加密。那么下面就带来python的具体实现步骤。
采用对称加密解密,即调用数据端按照顺序生成token,服务器端按照逆顺序解析token,并从中解析出时间戳,验证时间戳有效期,有效则返回数据。
首先对一串小写大写字母及数字字符串随机打乱顺序,生成一串专属的秘钥字符串 miwen
。在两台服务器都保存该段秘钥。
yuan="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
miwen="VTJBN64h1EMlwzq9ucKDxikmOtR8re3WypCS2HYZULsIg7aFPA5nb0fvjXQdoG"
然后写一个将字符串转换为base64的函数
import base64
def tob64(sstr):
sstr=sstr.encode()
bs4str = base64.b64encode(sstr)
return bs4str.decode()
然后再写一个生成随机字符串的函数,用于加密扰乱
import random
def randomstr(length=5):
pieces=[str(random.choice(yuan)) for i in range(int(length))]
return ''.join(pieces)
接着写一个密码表加密函数,根据我们的秘钥字符串,对传入的字符串进行替换加密
def jiami(thestr):
mistr=''
for letter in thestr:
if letter in yuan:
yuan_index=yuan.index(letter)
mi_letter=miwen[yuan_index]
mistr=mistr+mi_letter
else:
mistr=mistr+letter
return mistr
最后写一个生成token的方法,拼接时间与随机字符串,并用秘钥进行替换加密,生成一段用于传输给服务端验证的token。
import time
def geneat():
the_time=str(int(time.time()))
the_time=tob64(the_time)
the_time=randomstr()+"."+the_time+"."+randomstr()
the_time=tob64(the_time)
at=jiami(the_time)
return at
测试一下
验证其实就是将传入的token逆解析,然后验证时间戳是否过期即可
def deb64(bstr):#解析base64字符串
sstr=base64.b64decode(bstr)
sstr=sstr.decode()
return sstr
def jiemi(mistr):#根据秘钥替换解密回原来的字符串
thestr=''
for letter in mistr:
if letter in miwen:
mi_index=miwen.index(letter)
the_letter=yuan[mi_index]
thestr=thestr+the_letter
else:
thestr=thestr+letter
return thestr
def returntime(at):#提取出token中时间戳的那个部分
the_time=jiemi(at)
the_time=deb64(the_time)
the_time=the_time.split(".")[1]
the_time=deb64(the_time)
return the_time
def checkat(at):#组合上面的函数,判断时间戳是否有效,此处设置的是时间戳与服务器时间相差100秒内都有效
try:
the_time=returntime(at)
if abs(int(the_time)-time.time())<100:
return "ok"
else:
return "invalid"
except:
return "invalid"
测试一下,将上图中的那个字符串传入验证,因为已过期,所以显示失效
我们重新生成一个,然后马上再验证试下,可以看到,在有效期内,验证器返回OK
至此一个简单的token验证就完成了,在开放一些需要保密的接口时就可通过简单的token验证来保证安全了。
比如在flask上就可以这样使用
@app.route("/api/getsomething")
def getSomething():
token=request.args.get("token")
if checkat(token)!="ok":
return 'access denied'
...
return something
然后在调用接口的时候传入就行
import requests
def getSomething():
token=geneat()
params={'token':token}
resp=requests.get('https://felixlee.cn/api/getsomething',params=params)
return resp
上面添加一步扰乱字符串的原因是因为,如果单单对时间戳字符串进行base64加密及密码表替换的话,很容易看出规律来的,而在生成过程中,在首尾加上随机字符串则能很好地打乱规律,更安全一些。