我正在使用Pyramid作为回合制视频游戏数据传输的基础。客户端使用POST数据提交他们的操作,使用GET来检索序列化的游戏板数据。游戏数据有时可能包含字符串,但几乎总是两个整数和两个元组:
gamedata = (userid, gamenumber, (sourcex, sourcey), (destx, desty))
我的一般客户端框架是使用Pickle,转换为base64,使用urlencode并提交POST。然后服务器接收POST,解压缩单项字典,解码base64,然后反序列化数据对象。
我想使用Pickle,因为我可以使用类和值。将游戏数据作为POST字段提交只能给我字符串。
然而,Pickle被认为是不安全的。所以,我转向了pyYAML,它具有相同的目的。使用yaml.safe_load(data)
,我可以序列化数据而不会暴露安全漏洞。然而,safe_load非常安全,我甚至不能反序列化无害的元组或列表,即使它们只包含整数。
这里有什么中间地带吗?有没有一种方法可以序列化python结构,而不同时允许执行任意代码?
我的第一个想法是编写一个包装器来使用下划线在值名称中重新创建元组,例如,发送会将字典值source:(x,y)
转换为source_0:x,source_1:y
。我的第二个想法是这不是一种明智的开发方式。
编辑:这是我使用JSON的实现...它似乎不像YAML或Pickle那样强大,但我仍然担心可能存在安全漏洞。
客户端的构建在我进行实验时更加可见:
import urllib, json, base64
arbitrarydata = { 'id':14, 'gn':25, 'sourcecoord':(10,12), 'destcoord':(8,14)}
jsondata = json.dumps(arbitrarydata)
b64data = base64.urlsafe_b64encode(jsondata)
transmitstring = urllib.urlencode( [ ('data', b64data) ] )
urllib.urlopen('http://127.0.0.1:9000/post', transmitstring).read()
Pyramid服务器可以检索数据对象:
json.loads(base64.urlsafe_b64decode(request.POST['data'].encode('ascii')))
除此之外,我很想听听其他人对于在这种方法中使用POST数据的可接受性的看法。目前我的游戏客户端并不是基于浏览器的。