Пустой сессионный cookie вызывает ошибку в request.user

Конечный пользователь каким-то образом оказался с пустым файлом cookie для сессии (как в "sessionid=;"). Это вызывает следующий стек вызовов ошибок (ниже вызова функции request.user) при использовании Django в сочетании с GAE:

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:

>>> 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 ответ

Решение

Хорошо, я думаю, что мне, возможно, придется добавить класс промежуточного программного обеспечения для обработки этого особого случая и поместить его непосредственно после 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 проверяет только сеанс None, прежде чем искать в db (не пустой строке), и запрос первичного ключа с пустой строкой в ​​djangoappengine вызывает исключение. Я не уверен, что есть другой способ справиться с этим делом.

Другие вопросы по тегам