Ticket #5549: session-refactoring.diff

File session-refactoring.diff, 5.6 KB (added by Tomáš Horáček, 16 years ago)

Patch removes duplicity in code and corrects session documentation

  • django-trunk/django/contrib/sessions/models.py

     
    1 import os
    2 import sys
    3 import time
    4 import datetime
    5 import base64
    6 import md5
    7 import random
    8 import cPickle as pickle
    9 
    101from django.db import models
    112from django.utils.translation import ugettext_lazy as _
    12 from django.conf import settings
    133
    14 class SessionManager(models.Manager):
    15     def encode(self, session_dict):
    16         "Returns the given session dictionary pickled and encoded as a string."
    17         pickled = pickle.dumps(session_dict)
    18         pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
    19         return base64.encodestring(pickled + pickled_md5)
    20 
    21     def get_new_session_key(self):
    22         "Returns session key that isn't being used."
    23         # The random module is seeded when this Apache child is created.
    24         # Use SECRET_KEY as added salt.
    25         try:
    26             pid = os.getpid()
    27         except AttributeError:
    28             # No getpid() in Jython, for example
    29             pid = 1
    30         while 1:
    31             session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1), pid, time.time(), settings.SECRET_KEY)).hexdigest()
    32             try:
    33                 self.get(session_key=session_key)
    34             except self.model.DoesNotExist:
    35                 break
    36         return session_key
    37 
    38     def get_new_session_object(self):
    39         """
    40         Returns a new session object.
    41         """
    42         # FIXME: There is a *small* chance of collision here, meaning we will
    43         # return an existing object. That can be fixed when we add a way to
    44         # validate (and guarantee) that non-auto primary keys are unique. For
    45         # now, we save immediately in order to reduce the "window of
    46         # misfortune" as much as possible.
    47         created = False
    48         while not created:
    49             obj, created = self.get_or_create(session_key=self.get_new_session_key(),
    50                     expire_date = datetime.datetime.now())
    51             # Collision in key generation, so re-seed the generator
    52             random.seed()
    53         return obj
    54 
    55     def save(self, session_key, session_dict, expire_date):
    56         s = self.model(session_key, self.encode(session_dict), expire_date)
    57         if session_dict:
    58             s.save()
    59         else:
    60             s.delete() # Clear sessions with no data.
    61         return s
    62 
    634class Session(models.Model):
    645    """
    65     Django provides full support for anonymous sessions. The session
    66     framework lets you store and retrieve arbitrary data on a
    67     per-site-visitor basis. It stores data on the server side and
    68     abstracts the sending and receiving of cookies. Cookies contain a
    69     session ID -- not the data itself.
    70 
    71     The Django sessions framework is entirely cookie-based. It does
    72     not fall back to putting session IDs in URLs. This is an intentional
    73     design decision. Not only does that behavior make URLs ugly, it makes
    74     your site vulnerable to session-ID theft via the "Referer" header.
    75 
     6    Saves sessions in database.
     7   
     8    Not for direct usage, please use SessionStore class
     9    in django.contrib.sessions.backends.db module to access sessions.
     10   
    7611    For complete documentation on using Sessions in your code, consult
    7712    the sessions documentation that is shipped with Django (also available
    7813    on the Django website).
     
    8015    session_key = models.CharField(_('session key'), max_length=40, primary_key=True)
    8116    session_data = models.TextField(_('session data'))
    8217    expire_date = models.DateTimeField(_('expire date'))
    83     objects = SessionManager()
    8418
    8519    class Meta:
    8620        db_table = 'django_session'
    8721        verbose_name = _('session')
    8822        verbose_name_plural = _('sessions')
    89 
    90     def get_decoded(self):
    91         encoded_data = base64.decodestring(self.session_data)
    92         pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
    93         if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
    94             from django.core.exceptions import SuspiciousOperation
    95             raise SuspiciousOperation, "User tampered with session cookie."
    96         try:
    97             return pickle.loads(pickled)
    98         # Unpickling can cause a variety of exceptions. If something happens,
    99         # just return an empty dictionary (an empty session).
    100         except:
    101             return {}
  • django-trunk/docs/sessions.txt

     
    202202    >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
    203203    >>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10)
    204204    >>> s['last_login']
    205     datetime.datetime(2005, 8, 20, 13, 35, 0)
     205    datetime.datetime(2005, 8, 20, 13, 35, 10)
    206206    >>> s.save()
    207207
    208208If you're using the ``django.contrib.sessions.backends.db`` backend, each
     
    215215    >>> s.expire_date
    216216    datetime.datetime(2005, 8, 20, 13, 35, 12)
    217217
    218 Note that you'll need to call ``get_decoded()`` to get the session dictionary.
     218Note that you'll need to use ``SessionStore`` class
     219in the ``django.contrib.sessions.backends.db`` to get the session dictionary.
    219220This is necessary because the dictionary is stored in an encoded format::
    220221
    221222    >>> s.session_data
    222223    'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
    223     >>> s.get_decoded()
    224     {'user_id': 42}
    225224
    226225When sessions are saved
    227226=======================
Back to Top