GAE:cookies vs datastore

时间:2013-07-17 09:50:35

标签: python google-app-engine session-cookies app-engine-ndb

在寻找一种在我的应用中建立会话的有效方式时,我找到了GAE BoilerplateGAE Sessions

GAEB非常棒但是我的需求非常庞大:我不需要联邦登录或默认的用户结构,但我喜欢设计结构和他们解决某些问题的方式(路线,表格......)。 / p>

GAES非常简单但功能强大,可以治疗会话。我最喜欢的是它将所有内容存储在cookie中的方式,在这种情况下,它将完整的用户实体存储在cookie中,因此在下一页调用中,不会执行其他数据存储命中:始终从cookie中读取用户数据(这需要,如果用户更新某些内容,通常会更新数据,这是不常见的。)

另一方面,GAEB仅存储用户ID,然后在每次页面调用时检索用户名和用户电子邮件。这是它使用的BaseHandler代码的一部分(GAEB使用NDB模型):

@webapp2.cached_property
def username(self):
    if self.user:
        try:
            user_info = models.User.get_by_id(long(self.user_id))
            if not user_info.activated:
                self.auth.unset_session()
                self.redirect_to('home')
            else:
                return str(user_info.username)
        except AttributeError, e:
            # avoid AttributeError when the session was delete from the server
            logging.error(e)
            self.auth.unset_session()
            self.redirect_to('home')
    return None

电子邮件相同,而在render_template函数中,它执行此操作:

def render_template(self, filename, **kwargs):
    .... some code.....

    # set or overwrite special vars for jinja templates
    kwargs.update({
        'app_name': self.app.config.get('app_name'),
        'user_id': self.user_id,
        'username': self.username,
        'email': self.email,
        ... more vars ...
    })
    kwargs.update(self.auth_config)

似乎从数据存储中读取了2次(一个用户名,一个用于电子邮件),因为此funcs使models.User.get_by_**field**(long(self.user_id))

我唯一不知道究竟是什么意思的是@ webapp2.cached_property,这可能意味着所有这些数据存储读取都是从缓存中完成的,并且确实没有达到数据存储区。

有人能告诉我保存点击数据库的更好解决方案是什么?似乎最好将所有用户数据放在cookie中(显然是安全的)并且不会在每次页面调用时都访问数据存储区,但也许我错了(我是GAE的相对noob)以及所有这些读取到数据存储区是缓存的,然后是免费的。

1 个答案:

答案 0 :(得分:1)

强烈建议不要在Cookie中保存会话数据:

  • 必须根据每个请求进行转移(移动连接速度慢)
  • 您可以传输到GAE的HTTP标头大小是有限的(如果我没记错的话,是64Kb) - 这就是您可以存储的数据的上限
  • 即使您对会话进行加密和签名,您仍然容易受到回复攻击(无法安全地执行注销)

我不知道您提到的实施,但我们在CMS中有会话实施,请参阅https://bitbucket.org/viur/server/src/b2e9e3dca3adabee97e1761d630600a387a02c44/session.py?at=master。 一般的想法是生成随机字符串(用作会话标识符)。 在会话加载时,执行数据存储“按键获取”(缓存,因此如果该对象仍在内存缓存中,则根本不会访问数据存储区)。

只有在会话中存储的数据发生更改或会话尚未更改时才会执行保存 最近5分钟更新。 然后,您可以将用户对象的值复制到会话中,并且不会有其他数据存储请求。