在Google App Engine中,如何检查由urlsafe创建的密钥的输入有效性? [英] In Google App Engine, how to check input validity of Key created by urlsafe?

查看:92
本文介绍了在Google App Engine中,如何检查由urlsafe创建的密钥的输入有效性?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我从用户输入websafe url创建一个键
$ b $ $ p $ $ $ c $ key $ ndb.Key(urlsafe = some_user_input)

如何检查 some_user_input 是否有效?



我当前的实验显示上面的语句会抛出 ProtocolBufferDecodeError(无法从字符串合并。)异常,如果 some_user_input 无效,但从API中找不到任何关于此的信息。有人可以证实这一点,并指出我一些更好的方式来进行用户输入有效性检查,而不是捕获异常吗?



非常感谢!

解决方案

如果您尝试使用无效的urlsafe参数构造密钥

  key = ndb.Key(urlsafe ='bogus123')



 追溯(最近一次调用最后):
文件/ opt / google / google_appengine / google / appengine / runtime /wsgi.py,第240行,处理
handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
文件/opt/google/google_appengine/google/appengine/runtime/wsgi.py第299行,放在_LoadHandler
处理程序中,path,err = LoadObject(self._handler)
第85行中的/opt/google/google_appengine/google/appengine/runtime/wsgi.py文件LoadObject
obj = __import __(path [0])
文件/home/tim/git/teledap-appengine/main.py,第10行,in <模块>从src.tim导入处理程序
作为处理程序_
在< module>文件中的/home/tim/git/teledap-appengine/src/tim/handlers.py,第42行,
class ResetHandler(BaseHandler):
文件/home/tim/git/teledap-appengine/src/tim/handlers.py,行47,在ResetHandler
key = ndb.Key (urlsafe ='bogus123')
文件/opt/google/google_appengine/google/appengine/ext/ndb/key.py,第212行,位于__new__
self .__ reference = _ConstructReference(cls, ** kwargs)
文件/opt/google/google_appengine/google/appengine/ext/ndb/utils.py,第142行,位置定位器
返回包装(* args,** kwds)
文件/opt/google/google_appengine/google/appengine/ext/ndb/key.py,行642,位于_ConstructReference
reference = _ReferenceFromSerialized(serialized)
文件/ opt / google / google_appengine / google_appengine / google / appengine / datastore /entity_pb.py,第1710行,在__init__
中,如果内容不是None:self.MergeFromString(contents)
Fi le/opt/google/google_appengine/google/net/proto/ProtocolBuffer.py,第152行,位于MergeFromString
self.MergePartialFromString(s)
文件/ opt / google / google_appengine / google / net / proto / ProtocolBuffer.py,第168行,位于MergePartialFromString
self.TryMerge(d)
文件/opt/google/google_appengine/google/appengine/datastore/entity_pb.py,第1839行,在TryMerge
d.skipData(tt)
文件/opt/google/google_appengine/google/net/proto/ProtocolBuffer.py,第677行,在skipData
中引发ProtocolBufferDecodeError,损坏
ProtocolBufferDecodeError:损坏

有趣的是

 在_ReferenceFromSerialized 
中返回entity_pb文件/opt/google/google_appengine/google/appengine/ext/ndb/key.py,第773行。引用(序列化)

这是 key.py模块

  
如果不是isinstance(序列化,basestring):
raise TypeError('serialized must be a串;收到%r'%序列化)
elif isinstance(序列化,unicode):
serialized = serialized.encode('utf8')
返回entity_pb.Reference(序列化)

序列化这里是解码的urlsafe字符串,您可以阅读更多关于它的信息在链接到源代码。

另一个有趣的是最后一个:

  TryMerge 

$ b中的文件/opt/google/google_appengine/google/appengine/datastore/entity_pb.py,第1839行
$ b

位于 entity_pb.py模块看起来像这样

  def TryMerge(self,d):
while d.avail()> 0:
tt = d.getVarInt32()
if tt == 106:
self.set_app(d.getPrefixedString())
continue
if tt == 114:
length = d.getVarInt32()
tmp = ProtocolBuffer.Decoder(d.buffer(),d.pos(),d.pos()+ length)
d.skip (长度)
self.mutable_path()。TryMerge(tmp)
继续
如果tt == 162:
self.set_name_space(d.getPrefixedString())
继续


if(tt == 0):raise ProtocolBuffer.ProtocolBufferDecodeError
d.skipData(tt)

这是实际尝试将输入合并到Key中的地方。




您可以在源代码中看到,在从urlsafe参数构建Key的过程中,出错。首先它检查输入是否是一个字符串,如果不是,会引发一个 TypeError ,如果它是,但它不是有效的,确实a code> ProtocolBufferDecodeError 被引发。 >我的当前实验显示,如果some_user_input无效,但是无法从API中找到任何有关此信息的内容,则上面的语句将抛出ProtocolBufferDecodeError(无法从字符串合并)异常。有人可以证实这一点


已确认的分类 - 我们现在知道也可以引发TypeError。


并指向我一些更好的方式来进行用户输入有效性检查而不是捕获异常?

这是检查有效性的极好方法!为什么要检查自己,如果他们已经通过appengine完成了?一个代码片段可能看起来像这样(不是工作代码,只是一个例子)

$ $ $ $ $ $ c $ def $(自己)
#首先,从某处获取user_input

尝试:
key = ndb.Key(urlsafe = user_input)
TypeError:
return'对不起,只有字符串是允许为urlsafe输入'
,除ProtocolBufferDecodeError:
返回'对不起,urlsafe字符串似乎无效'


Suppose I create a key from user input websafe url

key = ndb.Key(urlsafe=some_user_input)

How can I check if the some_user_input is valid?

My current experiment shows that statement above will throw ProtocolBufferDecodeError (Unable to merge from string.) exception if the some_user_input is invalid, but could not find anything about this from the API. Could someone kindly confirm this, and point me some better way for user input validity checking instead of catching the exception?

Thanks a lot!

解决方案

If you try to construct a Key with an invalid urlsafe parameter

key = ndb.Key(urlsafe='bogus123')

you will get an error like

Traceback (most recent call last):
  File "/opt/google/google_appengine/google/appengine/runtime/wsgi.py", line 240, in Handle
    handler = _config_handle.add_wsgi_middleware(self._LoadHandler())
  File "/opt/google/google_appengine/google/appengine/runtime/wsgi.py", line 299, in _LoadHandler
    handler, path, err = LoadObject(self._handler)
  File "/opt/google/google_appengine/google/appengine/runtime/wsgi.py", line 85, in LoadObject
    obj = __import__(path[0])
  File "/home/tim/git/teledap-appengine/main.py", line 10, in <module>
    from src.tim import handlers as handlers_
  File "/home/tim/git/teledap-appengine/src/tim/handlers.py", line 42, in <module>
    class ResetHandler(BaseHandler):
  File "/home/tim/git/teledap-appengine/src/tim/handlers.py", line 47, in ResetHandler
    key = ndb.Key(urlsafe='bogus123')
  File "/opt/google/google_appengine/google/appengine/ext/ndb/key.py", line 212, in __new__
    self.__reference = _ConstructReference(cls, **kwargs)
  File "/opt/google/google_appengine/google/appengine/ext/ndb/utils.py", line 142, in positional_wrapper
    return wrapped(*args, **kwds)
  File "/opt/google/google_appengine/google/appengine/ext/ndb/key.py", line 642, in _ConstructReference
    reference = _ReferenceFromSerialized(serialized)
  File "/opt/google/google_appengine/google/appengine/ext/ndb/key.py", line 773, in _ReferenceFromSerialized
    return entity_pb.Reference(serialized)
  File "/opt/google/google_appengine/google/appengine/datastore/entity_pb.py", line 1710, in __init__
    if contents is not None: self.MergeFromString(contents)
  File "/opt/google/google_appengine/google/net/proto/ProtocolBuffer.py", line 152, in MergeFromString
    self.MergePartialFromString(s)
  File "/opt/google/google_appengine/google/net/proto/ProtocolBuffer.py", line 168, in MergePartialFromString
    self.TryMerge(d)
  File "/opt/google/google_appengine/google/appengine/datastore/entity_pb.py", line 1839, in TryMerge
    d.skipData(tt)
  File "/opt/google/google_appengine/google/net/proto/ProtocolBuffer.py", line 677, in skipData
    raise ProtocolBufferDecodeError, "corrupted"
ProtocolBufferDecodeError: corrupted

Interesting here are is

File "/opt/google/google_appengine/google/appengine/ext/ndb/key.py", line 773, in _ReferenceFromSerialized
  return entity_pb.Reference(serialized)

which is the last code executed in the key.py module:

def _ReferenceFromSerialized(serialized):
  """Construct a Reference from a serialized Reference."""
  if not isinstance(serialized, basestring):
    raise TypeError('serialized must be a string; received %r' % serialized)
  elif isinstance(serialized, unicode):
    serialized = serialized.encode('utf8')
  return entity_pb.Reference(serialized)

serialized here being the decoded urlsafe string, you can read more about it in the link to the source code.

another interesting one is the last one:

File "/opt/google/google_appengine/google/appengine/datastore/entity_pb.py",   line 1839, in TryMerge

in the entity_pb.py module which looks like this

  def TryMerge(self, d):
    while d.avail() > 0:
      tt = d.getVarInt32()
      if tt == 106:
        self.set_app(d.getPrefixedString())
        continue
      if tt == 114:
        length = d.getVarInt32()
        tmp = ProtocolBuffer.Decoder(d.buffer(), d.pos(), d.pos() + length)
        d.skip(length)
        self.mutable_path().TryMerge(tmp)
        continue
      if tt == 162:
        self.set_name_space(d.getPrefixedString())
        continue


      if (tt == 0): raise ProtocolBuffer.ProtocolBufferDecodeError
      d.skipData(tt)

which is where the actual attempt to 'merge the input to into a Key' is made.


You can see in the source code that during the process of constructing a Key from an urlsafe parameter not a whole lot can go wrong. First it checks if the input is a string and if it's not, a TypeError is raised, if it is but it's not 'valid', indeed a ProtocolBufferDecodeError is raised.


My current experiment shows that statement above will throw ProtocolBufferDecodeError (Unable to merge from string.) exception if the some_user_input is invalid, but could not find anything about this from the API. Could someone kindly confirm this

Sort of confirmed - we now know that also TypeError can be raised.

and point me some better way for user input validity checking instead of catching the exception?

This is an excellent way to check validity! Why do the checks yourself if the they are already done by appengine? A code snippet could look like this (not working code, just an example)

def get(self):
  # first, fetch the user_input from somewhere

  try:
    key = ndb.Key(urlsafe=user_input)
  except TypeError:
    return 'Sorry, only string is allowed as urlsafe input'
  except ProtocolBufferDecodeError:
    return 'Sorry, the urlsafe string seems to be invalid'

这篇关于在Google App Engine中,如何检查由urlsafe创建的密钥的输入有效性?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆