空白的sessionid cookie在request.user中导致错误

时间:2014-03-04 21:15:14

标签: django-nonrel djangoappengine

最终用户以某种方式结束了他们的sessionid cookie为空(如“sessionid =;”)。当将Django与GAE结合使用时,这会导致以下错误调用堆栈(在函数调用request.user下面):

File "/src/django/utils/functional.py", line 204, in inner
    self._setup()
  File "/src/django/utils/functional.py", line 270, in _setup
    self._wrapped = self._setupfunc()
  File "/src/django/contrib/auth/middleware.py", line 18, in <lambda>
    request.user = SimpleLazyObject(lambda: get_user(request))
  File "/src/django/contrib/auth/middleware.py", line 10, in get_user
    request._cached_user = auth.get_user(request)
  File "/src/django/contrib/auth/__init__.py", line 136, in get_user
    user_id = request.session[SESSION_KEY]
  File "/src/django/contrib/sessions/backends/base.py", line 44, in __getitem__
    return self._session[key]
  File "/src/django/contrib/sessions/backends/base.py", line 167, in _get_session
    self._session_cache = self.load()
  File "/src/django/contrib/sessions/backends/cached_db.py", line 39, in load
    expire_date__gt=timezone.now()
  File "/src/django/db/models/manager.py", line 143, in get
    return self.get_query_set().get(*args, **kwargs)
  File "/src/django/db/models/query.py", line 398, in get
    num = len(clone)
  File "/src/django/db/models/query.py", line 106, in __len__
    self._result_cache = list(self.iterator())
  File "/src/django/db/models/query.py", line 317, in iterator
    for row in compiler.results_iter():
  File "/src/djangotoolbox/db/basecompiler.py", line 375, in results_iter
    results = self.build_query(fields).fetch(
  File "/src/djangotoolbox/db/basecompiler.py", line 481, in build_query
    query.add_filters(self.query.where)
  File "/src/djangotoolbox/db/basecompiler.py", line 174, in add_filters
    self.add_filters(child)
  File "/src/djangotoolbox/db/basecompiler.py", line 176, in add_filters
    field, lookup_type, value = self._decode_child(child)
  File "/src/djangotoolbox/db/basecompiler.py", line 216, in _decode_child
    lookup_type, value, field, annotation)
  File "/src/djangotoolbox/db/basecompiler.py", line 254, in _normalize_lookup_value
    return self.ops.value_for_db(value, field, lookup_type)
  File "/src/djangoappengine/db/base.py", line 128, in value_for_db
    return super_value_for_db(value, field, lookup)
  File "/src/djangotoolbox/db/base.py", line 245, in value_for_db
    field_kind, db_type, lookup)
  File "/src/djangoappengine/db/base.py", line 160, in _value_for_db
    raise DatabaseError("Only strings and positive integers "
DatabaseError: Only strings and positive integers may be used as keys on GAE.

如果sessionid设置为某个无效的非空值(例如“session = garbage;”),则不会发生此错误。我认为这与跟踪python shell中的行为对比有关:

>>> Session.objects.filter(session_key='abc').exists()
0
>>> Session.objects.filter(session_key='').exists()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/src/django/db/models/query.py", line 610, in exists
    return self.query.has_results(using=self.db)
  File "/src/django/db/models/sql/query.py", line 445, in has_results
    return compiler.has_results()
  File "/src/dbindexer/compiler.py", line 32, in has_results
    return super(SQLCompiler, self).has_results()
  File "/src/djangotoolbox/db/basecompiler.py", line 384, in has_results
    return self.get_count(check_exists=True)
  File "/src/djangotoolbox/db/basecompiler.py", line 468, in get_count
    return self.build_query().count(high_mark)
  File "/src/djangotoolbox/db/basecompiler.py", line 481, in build_query
    query.add_filters(self.query.where)
  File "/src/djangotoolbox/db/basecompiler.py", line 174, in add_filters
    self.add_filters(child)
  File "/src/djangotoolbox/db/basecompiler.py", line 176, in add_filters
    field, lookup_type, value = self._decode_child(child)
  File "/src/djangotoolbox/db/basecompiler.py", line 216, in _decode_child
    lookup_type, value, field, annotation)
  File "/src/djangotoolbox/db/basecompiler.py", line 254, in _normalize_lookup_value
    return self.ops.value_for_db(value, field, lookup_type)
  File "/src/djangoappengine/db/base.py", line 128, in value_for_db
    return super_value_for_db(value, field, lookup)
  File "/src/djangotoolbox/db/base.py", line 245, in value_for_db
    field_kind, db_type, lookup)
  File "/src/djangoappengine/db/base.py", line 160, in _value_for_db
    raise DatabaseError("Only strings and positive integers "
DatabaseError: Only strings and positive integers may be used as keys on GAE.

这是djangoappengine或djangotoolbox错误,还是Django错误?什么是防止此错误的正确方法,并考虑用户未经身份验证?

1 个答案:

答案 0 :(得分:1)

好吧,我想我可能需要添加一个中间件类来处理这种特殊情况,并在SessionMiddleware之后直接放置它:

class EmptySessionMiddleware(object):
    def process_request(self, request):

        session = request.session

        if session.session_key is not None and len(session.session_key) == 0:
            logging.info('[EmptySessionMiddleware] setting empty session key to None')
            session._session_key = None

这是一个奇怪的特殊情况,但基本上问题是Django会话中间件只在查找db(非空字符串)之前检查None会话,并且djangoappengine中的空字符串主键查询引发异常。我不确定还有另一种处理这种情况的方法。