将Google App Engine实体密钥传递到网页以维护上下文是否安全?

时间:2011-07-25 04:53:56

标签: python google-app-engine entity google-cloud-datastore key

我有一个简单的GAE系统,其中包含Account,Project和Transaction的模型。

我正在使用Django生成一个网页,其中包含属于给定帐户的表格中的项目列表,我想创建指向每个项目详细信息页面的链接。我正在生成一个链接,将Project的键转换为字符串,并在链接中包含该链接,以便于查找Project对象。这给出了一个如下所示的链接:

<a href="/project?key=agxkZAB-bnVpY2VrbXRyDDsSBkNvdXBvbhgBDA">My Project Name</a>
  1. 创建像这样的链接是否安全?有没有更好的办法?感觉这是保持背景的一种坏方法。

  2. 键字符串显示在链接页面中并且很难看。有没有办法避免显示它?

  3. 感谢。

5 个答案:

答案 0 :(得分:6)

在GAE文档中,使用相同方法的示例很少,而且Key使用安全字符来包含在URL中。所以,可能没有问题。

BTW,我更喜欢使用数字ID(obj_key.id()),当我的模型使用数字作为标识符时,只是因为它看起来不那么难看。

答案 1 :(得分:5)

这是否“安全”取决于您的意思,以及您如何实施您的应用。让我们退一步,看看究竟是什么存储在Key对象中。拿起钥匙,转到shell.appspot.com,然后输入以下内容:

db.Key(your_key)

返回如下内容:

datastore_types.Key.from_path(u'TestKind', 1234, _app=u'shell')

如您所见,密钥包含App ID,种类名称,ID或名称(以及任何父实体的种类/ ID对 - 在本例中为none)。在这里你什么都不应该特别关注隐藏,所以这里不应该有任何重大的信息泄露风险。

您提到用户可能会猜到其他网址 - 这当然是可能的,因为他们可以解码密钥,修改ID或名称,然后重新编码密钥。但是,如果您的安全模型依赖于而不是猜测其他网址,那么您可能需要执行以下操作之一:

  1. 重新考虑您应用的安全模型。如果可以避免,您不应该依赖“秘密URL”来获得任何程度的真实安全。
  2. 使用密钥名称,并将其设置为用户无法猜测的长随机字符串。
  3. 最后一个问题是用户可以修改的内容。如果您通过将密钥传递给db.get来处理密钥,则用户可以更改类型名称,并使您获取与您预期的不同的实体类型。如果该实体类恰好具有类似命名的字段,那么您可能会对实体执行某些操作(例如从中显示数据),而这些实体并不是您想要的。您可以通过将密钥传递给YourModel.get来避免这种情况,这将在获取密钥之前检查密钥是否正确。

    所有这些都表示,更好的方法是传递密钥ID或名称。您可以通过在密钥对象上调用.id()来提取此内容(如果您使用的是密钥名称,则为.name()),并且可以使用db.Key.from_path('kind_name', id)重建原始密钥 - 或者只是使用YourModel.get_by_id直接获取实体。

答案 2 :(得分:3)

在做了一些研究之后,我想我现在可以回答我自己的问题了。我想知道使用GAE密钥或ID本身是不安全的。

事实上,没有一些额外的代码,它是不安全的,因为用户可以修改返回的网页中的URL或访问他们手动构建的URL。这可能会让经过身份验证的用户仅通过更改URL中的密钥ID来编辑其他用户的数据。

因此,对于您允许访问的每个资源,您需要确保当前经过身份验证的用户有权以他们尝试的方式访问它。

这涉及为每个操作编写额外的查询,因为似乎没有内置的方法只是说“用户只能访问他们拥有的对象”。

答案 3 :(得分:2)

我知道这是一个老帖子,但我想澄清一件事。有时您需要使用KEY。

如果您的实体具有@Parent关系,您无法通过其ID获取它,则需要使用整个KEY将其从数据存储区中恢复。在这些情况下,如果要检索实体,则需要始终使用KEY。

答案 4 :(得分:1)

它们不仅仅是在增加;我的数据存储区中只有10个条目,我已经达到了7001个。 只要有某种形式的保护,以便用户不能简单地猜测它们,就没有理由不这样做。