Python 将Google应用程序引擎实体密钥传递到网页以维护上下文安全吗?

Python 将Google应用程序引擎实体密钥传递到网页以维护上下文安全吗?,python,google-app-engine,entity,google-cloud-datastore,key,Python,Google App Engine,Entity,Google Cloud Datastore,Key,我有一个简单的GAE系统,它包含帐户、项目和事务的模型 我正在使用Django生成一个网页,该网页在一个表中包含属于给定帐户的项目列表,我希望创建一个指向每个项目详细信息页面的链接。我正在生成一个链接,将项目的键转换为字符串,并将其包含在链接中,以便于查找项目对象。这将提供一个如下所示的链接: <a href="/project?key=agxkZAB-bnVpY2VrbXRyDDsSBkNvdXBvbhgBDA">My Project Name</a> 创建这样的

我有一个简单的GAE系统,它包含帐户、项目和事务的模型

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

<a href="/project?key=agxkZAB-bnVpY2VrbXRyDDsSBkNvdXBvbhgBDA">My Project Name</a>

  • 创建这样的链接安全吗?有更好的办法吗?这感觉像是一个不好的保持上下文的方法

  • 该键字符串显示在链接页面中,并且很难看。有没有办法避免显示出来


  • 谢谢。

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


    顺便说一句,当我的模型使用数字作为标识符时,我更喜欢使用数字ID(
    obj_key.ID()
    ),因为它看起来不那么难看。

    这是否“安全”取决于你的意思,以及你如何实现你的应用程序。让我们退后一点,看看键对象中到底存储了什么。带上钥匙,转到
    shell.appspot.com
    ,然后输入以下内容:

    db.Key(your_key)
    
    datastore_types.Key.from_path(u'TestKind', 1234, _app=u'shell')
    
    这将返回如下内容:

    db.Key(your_key)
    
    datastore_types.Key.from_path(u'TestKind', 1234, _app=u'shell')
    
    如您所见,该键包含应用程序ID、种类名称和ID或名称(以及任何父实体的种类/ID对-在本例中为无)。这里没有什么你应该特别关注的隐藏,所以这里不应该有任何重大的信息泄漏风险

    您提到用户可能会猜测其他URL,这当然是可能的,因为他们可以解码密钥,修改ID或名称,并重新编码密钥。但是,如果您的安全模型依赖于它们,而不是猜测其他URL,那么您可能需要做以下几件事之一:

  • 重新考虑应用程序的安全模型。如果可以避免的话,你不应该依靠“秘密URL”来实现任何程度的真正安全性
  • 使用键名,并将其设置为用户无法猜测的长随机字符串
  • 最后一个问题是用户还可以修改什么。如果通过将密钥传递给db.get来处理密钥,则用户可以更改种类名称,并使您获取与预期不同的实体种类。如果该实体类型碰巧具有类似的命名字段,您可能会对该实体执行您不打算执行的操作(例如从中显示数据)。您可以通过将密钥传递给您的模型来避免这种情况。取而代之的是get,它将在获取密钥之前检查密钥的类型是否正确


    尽管如此,更好的方法是传递密钥ID或名称。您可以通过调用key对象上的
    .id()
    (对于id-
    .name()
    ,如果您使用的是key name),来提取这个值,并且您可以使用
    db.key.从\u path('kind\u name',id)
    )重构原始密钥,或者直接使用
    您的模型来获取实体。通过\u id
    获取\u它们不仅仅是增加;我的数据存储中只有10个条目,我已经达到7001。
    只要有某种形式的保护,让用户不能简单地猜测,就没有理由不这么做。

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

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

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


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

    我知道这是一篇老文章,但我想澄清一件事。有时你需要使用钥匙


    当您有一个具有@Parent关系的实体时,您无法通过其ID获取它,您需要使用整个键从数据存储中获取它。在这些情况下,如果要检索实体,您需要始终使用密钥。

    谢谢您的回复。我关心的不是键是否是URL安全的,而是用户根据看到的其他URL猜测其他URL。数字ID是简单的递增整数,似乎更容易破解。如果你需要安全的url,只能由所有者打开,你至少需要添加一个身份验证层,但使用数字ID时不要让url“难以猜测”+1。我一直在使用密钥,数字ID看起来更漂亮。我确实有一个使用Google登录的身份验证层,但你需要的不仅仅是授权。您需要确保当前用户可以访问每个资源。这需要编写很多额外的代码,但这是确保安全性所必需的。我只是希望通过设置数据库属性或其他什么来实现更自动化。这取决于您使用的框架,但我不想用任何标准和自动的方法来保护url。也许你必须自己去实现它