简体   繁体   English

GAE:Cookie与数据存储区

[英]GAE: cookies vs datastore

While looking for a good and efficient way to have a session in my app, I found GAE Boilerplate and GAE Sessions . 在寻找一种在我的应用程序中进行会话的好而有效的方式时,我发现了GAE BoilerplateGAE Sessions

GAEB is amazing but very vast for my needs: I don't need Federate Login nor a default User structure, but I like the design structure and the way they solved some issues (routes, forms,...). GAEB很棒,但是可以满足我的需求:我不需要联合登录,也不需要默认的用户结构,但是我喜欢设计结构以及它们解决某些问题(路线,表单等)的方式。

GAES is quite simple but powerfull to treat sessions. GAES非常简单,但是功能强大,可以处理会话。 The most I like is the way it stores everything in a cookie, in this case, it stores the full user entity in a cookie so in the next page calls, no other datastore hits are done: the user data is always read from the cookie (this need, obviusly to update the data if the user updates something, which is not usual). 我最喜欢的是将所有内容存储在cookie中的方式,在这种情况下,它将完整的用户实体存储在cookie中,因此在下一次页面调用中,没有其他数据存储命中完成:用户数据始终从cookie中读取(这很必要,如果用户更新某些内容,则很不方便地更新数据,这是不常见的)。

In the other hand, GAEB stores only the user ID and then retrieves, on each page call, the username and the user email. 另一方面,GAEB仅存储用户ID,然后在每次页面调用时检索用户名和用户电子邮件。 This is part of the code for the BaseHandler it uses (GAEB uses NDB model): 这是它使用的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

Same for email, and in the render_template function it does this: 与电子邮件相同,在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)

It seems that reads 2 times (one for username and one for email) from the datastore, because this funcs makes models.User.get_by_**field**(long(self.user_id)) 似乎从数据存储区中读取了2次(用户名一次,电子邮件一次),因为此models.User.get_by_**field**(long(self.user_id))创建了models.User.get_by_**field**(long(self.user_id))

The only thing I don't know exactly what means is the @webapp2.cached_property, that maybe means that all this datastore reads are done from a cache and really don't hit the datastore. 我唯一不知道确切是什么意思的是@ webapp2.cached_property,这可能意味着所有这些数据存储区的读取都是从缓存中完成的,实际上并没有命中数据存储区。

Can someone tell me what is the better solution to save hits to the database? 有人可以告诉我什么是将匹配数据保存到数据库的更好的解决方案吗? It seems that it is better to have all the user data in a cookie (obviously, secured) and don't hit the datastore on every page call, but maybe I'm mistaken (I'm relatively noob with GAE) and all this reads to datastore are cached and, then, for free. 似乎最好将所有用户数据存储在cookie中(显然是安全的),并且不要在每次页面调用时都访问数据存储区,但是也许我弄错了(我对GAE相对不满意),而所有这些对数据存储区的读取将被缓存,然后免费释放。

Saving session data in the cookie is highly discouraged: 不建议将会话数据保存在cookie中:

  • It has to be transfered with each request (slow on mobile connections) 必须随每个请求一起传输(移动连接速度很慢)
  • The HTTP Header size you can transfer to the GAE is limited (64Kb if i remember correctly) - thats the upper bound of data you could store 可以传输到GAE的HTTP标头大小有限(如果我没有记错的话,则为64Kb)-这就是您可以存储的数据上限
  • Even if you encrypt and sign your session, you would still be vulnerable to reply attacks (you cannot perform a logout safely) 即使您对会话进行加密和签名,您仍然容易受到回复攻击的影响(您无法安全地注销)

I don't know the implementations you mentioned, but we have an session implementation in our CMS, see https://bitbucket.org/viur/server/src/b2e9e3dca3adabee97e1761d630600a387a02c44/session.py?at=master . 我不知道您提到的实现,但是CMS中有一个会话实现,请参阅https://bitbucket.org/viur/server/src/b2e9e3dca3adabee97e1761d630600a387a02c44/session.py?at=master The general idea is to generate a random string (used as a session identifier). 总体思路是生成一个随机字符串(用作会话标识符)。 On session load a datastore "get by key" is performed (which is cached, so if that object is still in memcache, it wont hit the datastore at all). 在会话加载时,将执行数据存储“按键获取”(已缓存),因此,如果该对象仍在内存缓存中,则它根本不会命中数据存储。

And saving is only performed if the data stored inside the session changed or the session has not been updated for the last 5 minutes. 仅在会话中存储的数据已更改或在最近5分钟内未更新会话时,才执行保存。 Then you can copy the values of your user object into the session and wont have an additional datastore request. 然后,您可以将用户对象的值复制到会话中,而不会有其他数据存储请求。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM