执行 AppEngine 的数据存储。get() 不验证所请求密钥的命名空间?



我在go-appengine中使用了带有数据存储的命名空间,大致如下:

func getThing() *Thing {
  nctx := appengine.Namespace(ctx, "whatever")
  thing := Thing{}
  key, err := datastore.Get(nctx, key, &thing)
  if err != nil {
    return nil, err
  }
  return thing, nil
}

很简单,对吧?不幸的是,如果事实证明,如果 nctx 的命名空间与键的不匹配,它无论如何都会愉快地获取对象。AFAICT,无法手动获取密钥的"命名空间"字段以手动验证它。这对我们的应用程序很重要,因为我们有来自 Web 客户端的密钥,在某些边缘情况下,这些密钥可能与错误的命名空间相关联。

OTOH,如果我使用 Thing 的键作为祖先进行查询,数据存储(适当地)会返回错误,因为祖先的命名空间与上下文(形式为 query namespace is 'bar' but ancestor namespace is 'foo')之间的命名空间不匹配。

我是否缺少有关数据存储获取/查询和命名空间的预期约束的内容,或者这听起来像是一个错误?

我假设您正在传递编码密钥,而不仅仅是它们的 ID?如果使用datastore.NewKey创建密钥,则传递给该密钥的上下文将设置密钥的命名空间(除非还有父级,在这种情况下将使用命名空间)。

就意图而言,此行为等效于 python API - 在namespace_mananger上设置不同的命名空间时,可以获取从urlsafe字符串创建的密钥,但是如果您仅通过指定种类和id来创建密钥,则使用当前设置的命名空间。

不过,为命名空间提供一个 getter 会很好,所以你至少可以在反序列化后进行验证......