我有一个简单的GAE系统,其中包含Account,Project和Transaction的模型。
我正在使用Django生成一个网页,其中包含属于给定帐户的表格中的项目列表,我想创建指向每个项目详细信息页面的链接。我正在生成一个链接,将Project的键转换为字符串,并在链接中包含该链接,以便于查找Project对象。这给出了一个如下所示的链接:
<a href="/project?key=agxkZAB-bnVpY2VrbXRyDDsSBkNvdXBvbhgBDA">My Project Name</a>
创建像这样的链接是否安全?有没有更好的办法?感觉这是保持背景的一种坏方法。
键字符串显示在链接页面中并且很难看。有没有办法避免显示它?
感谢。
答案 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或名称,然后重新编码密钥。但是,如果您的安全模型依赖于而不是猜测其他网址,那么您可能需要执行以下操作之一:
最后一个问题是用户可以修改的内容。如果您通过将密钥传递给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个。 只要有某种形式的保护,以便用户不能简单地猜测它们,就没有理由不这样做。