【问题标题】:Webapp2_extras.auth with backend 'datastore' not working properly带有后端“数据存储”的 Webapp2_extras.auth 无法正常工作
【发布时间】:2015-02-26 15:50:50
【问题描述】:

将会话后端设置为数据存储区将无法正常工作,因为每次调用 auth.get_user_by_session() 都会导致会话实体的数据存储区发生 put(),即使您没有修改会话值。

这是因为调用 auth.get_user_by_session() 调用了 auth.get_session_data(pop=True)。 Pop=True 确实会从会话字典对象(来自 webapp2_extras.sessions 的 SessionDict)中弹出 _user,这会导致会话将属性 modified 设置为 True。

因此,当处理程序完成它的任务时,处理程序调度方法中对 save_session 的调用将检查会话是否已修改,如果为 True(始终为 TRUE!!!)将执行放入数据存储区。

因此,对于每个请求,会话都会被放入数据存储区,因为显然您在每个请求上都调用了 auth.get_user_by_session()。

我不知道如何处理这个问题,但我已经在 google 代码项目页面中打开了一个问题(似乎已被废弃): https://code.google.com/p/webapp-improved/issues/detail?id=100&sort=-id

谁能帮我理解这里发生了什么?我该如何解决这个问题?

【问题讨论】:

  • 你的问题的标题有点偏离......我认为 webapp2_extras.sessions 的行为符合预期,并且使用的后端不相关。您遇到的问题是 webapp2_extras.auth (我从未使用过它,但它对我来说看起来也很错误/很奇怪,因为这是值得的)。
  • 完全正确.. 我改了标题。问题出在 auth 模块上。为什么 get_session_data 从会话中弹出用户??

标签: google-app-engine python-2.7 webapp2


【解决方案1】:

所以,如果我们检查来自 webapp2_extras.auth 的以下代码,您会得到以下信息:

def get_user_by_session(self, save_session=True):
        """Returns a user based on the current session.

        :param save_session:
            If True, saves the user in the session if authentication succeeds.
        :returns:
            A user dict or None.
        """
        if self._user is None:
            data = self.get_session_data(pop=True)
            if not data:
                self._user = _anon
            else:
                self._user = self.get_user_by_token(
                    user_id=data['user_id'], token=data['token'],
                    token_ts=data['token_ts'], cache=data,
                    cache_ts=data['cache_ts'], remember=data['remember'],
                    save_session=save_session)
        return self._user_or_none()

之后让我们检查get_session_data()

def get_session_data(self, pop=False):
        """Returns the session data as a dictionary.

        :param pop:
            If True, removes the session.
        :returns:
            A deserialized session, or None.
        """
        func = self.session.pop if pop else self.session.get
        rv = func('_user', None)
        if rv is not None:
            data = self.store.deserialize_session(rv)
            if data:
                return data
            elif not pop:
                self.session.pop('_user', None)

        return None

如果会话中有用户,我看不出它为什么会弹出?它指向 user_or_none 如果用户是 None 则取消设置会话。

关于 webapp2 内置授权的精彩博文:

http://blog.abahgat.com/2013/01/07/user-authentication-with-webapp2-on-google-app-engine/

【讨论】:

  • 我不认为这是一个正确的答案。将 pop 设置为 True 将调用 self.session.pop('_user', None) 这会将会话属性设置为 True (参见 SessionDict 类),因此即使您不修改会话。
  • 是的,但如果会话中确实有用户,它永远不会被调用。
  • 是的,但请注意 self._user 用于为每个请求缓存用户。所以每个请求的第一次 self_user 总是无。见webapp-improved.appspot.com/_modules/webapp2_extras/…
  • 这里的关键是为什么从会话中弹出用户而不是直接获取它?看到 get_user_by_session pop=True 是硬编码的。你不能改变它。我认为这是一个错误。
  • FWIW,我同意 get_user_by_session 中的 (pop=True) 似乎是一个错误。可能值得发送带有修复程序的补丁并将其附加到您针对项目打开的问题中?
猜你喜欢
  • 2015-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多