문제

An end user somehow ended up with their sessionid cookie blank (as in "sessionid=;"). This causes the following error call stack (below the function call to request.user) when using Django in conjunction with 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.

This error does not occur if sessionid is set to some invalid non-empty value (such as "session=garbage;"). I think it is related to follow contrast of behavior in a 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.

Is this a djangoappengine or djangotoolbox bug, or a Django bug? What's the proper way to prevent this error, and consider user unauthenticated?

도움이 되었습니까?

해결책

Ok, I think I may have to add a middleware class to handle this special case, and place it directly after 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

It's a weird special case, but basically the problem is that Django session middleware only checks for None session before looking up in db (not empty string), and an empty string primary key query in djangoappengine raises an exception. I'm not sure there's another way to handle this case.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top