app/django/contrib/sessions/backends/base.py
changeset 54 03e267d67478
child 323 ff1a9aa48cfd
equal deleted inserted replaced
53:57b4279d8c4e 54:03e267d67478
       
     1 import base64
       
     2 import md5
       
     3 import os
       
     4 import random
       
     5 import sys
       
     6 import time
       
     7 from django.conf import settings
       
     8 from django.core.exceptions import SuspiciousOperation
       
     9 
       
    10 try:
       
    11     import cPickle as pickle
       
    12 except ImportError:
       
    13     import pickle
       
    14 
       
    15 class SessionBase(object):
       
    16     """
       
    17     Base class for all Session classes.
       
    18     """
       
    19     TEST_COOKIE_NAME = 'testcookie'
       
    20     TEST_COOKIE_VALUE = 'worked'
       
    21 
       
    22     def __init__(self, session_key=None):
       
    23         self._session_key = session_key
       
    24         self.accessed = False
       
    25         self.modified = False
       
    26 
       
    27     def __contains__(self, key):
       
    28         return key in self._session
       
    29 
       
    30     def __getitem__(self, key):
       
    31         return self._session[key]
       
    32 
       
    33     def __setitem__(self, key, value):
       
    34         self._session[key] = value
       
    35         self.modified = True
       
    36 
       
    37     def __delitem__(self, key):
       
    38         del self._session[key]
       
    39         self.modified = True
       
    40 
       
    41     def keys(self):
       
    42         return self._session.keys()
       
    43 
       
    44     def items(self):
       
    45         return self._session.items()
       
    46 
       
    47     def get(self, key, default=None):
       
    48         return self._session.get(key, default)
       
    49 
       
    50     def pop(self, key, *args):
       
    51         self.modified = self.modified or key in self._session
       
    52         return self._session.pop(key, *args)
       
    53 
       
    54     def setdefault(self, key, value):
       
    55         if key in self._session:
       
    56             return self._session[key]
       
    57         else:
       
    58             self.modified = True
       
    59             self._session[key] = value
       
    60             return value
       
    61 
       
    62     def set_test_cookie(self):
       
    63         self[self.TEST_COOKIE_NAME] = self.TEST_COOKIE_VALUE
       
    64 
       
    65     def test_cookie_worked(self):
       
    66         return self.get(self.TEST_COOKIE_NAME) == self.TEST_COOKIE_VALUE
       
    67 
       
    68     def delete_test_cookie(self):
       
    69         del self[self.TEST_COOKIE_NAME]
       
    70 
       
    71     def encode(self, session_dict):
       
    72         "Returns the given session dictionary pickled and encoded as a string."
       
    73         pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
       
    74         pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
       
    75         return base64.encodestring(pickled + pickled_md5)
       
    76 
       
    77     def decode(self, session_data):
       
    78         encoded_data = base64.decodestring(session_data)
       
    79         pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
       
    80         if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
       
    81             raise SuspiciousOperation("User tampered with session cookie.")
       
    82         try:
       
    83             return pickle.loads(pickled)
       
    84         # Unpickling can cause a variety of exceptions. If something happens,
       
    85         # just return an empty dictionary (an empty session).
       
    86         except:
       
    87             return {}
       
    88 
       
    89     def _get_new_session_key(self):
       
    90         "Returns session key that isn't being used."
       
    91         # The random module is seeded when this Apache child is created.
       
    92         # Use settings.SECRET_KEY as added salt.
       
    93         try:
       
    94             pid = os.getpid()
       
    95         except AttributeError:
       
    96             # No getpid() in Jython, for example
       
    97             pid = 1
       
    98         while 1:
       
    99             session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1),
       
   100                                   pid, time.time(), settings.SECRET_KEY)).hexdigest()
       
   101             if not self.exists(session_key):
       
   102                 break
       
   103         return session_key
       
   104 
       
   105     def _get_session_key(self):
       
   106         if self._session_key:
       
   107             return self._session_key
       
   108         else:
       
   109             self._session_key = self._get_new_session_key()
       
   110             return self._session_key
       
   111 
       
   112     def _set_session_key(self, session_key):
       
   113         self._session_key = session_key
       
   114 
       
   115     session_key = property(_get_session_key, _set_session_key)
       
   116 
       
   117     def _get_session(self):
       
   118         # Lazily loads session from storage.
       
   119         self.accessed = True
       
   120         try:
       
   121             return self._session_cache
       
   122         except AttributeError:
       
   123             if self._session_key is None:
       
   124                 self._session_cache = {}
       
   125             else:
       
   126                 self._session_cache = self.load()
       
   127         return self._session_cache
       
   128 
       
   129     _session = property(_get_session)
       
   130 
       
   131     # Methods that child classes must implement.
       
   132 
       
   133     def exists(self, session_key):
       
   134         """
       
   135         Returns True if the given session_key already exists.
       
   136         """
       
   137         raise NotImplementedError
       
   138 
       
   139     def save(self):
       
   140         """
       
   141         Saves the session data.
       
   142         """
       
   143         raise NotImplementedError
       
   144 
       
   145     def delete(self, session_key):
       
   146         """
       
   147         Clears out the session data under this key.
       
   148         """
       
   149         raise NotImplementedError
       
   150 
       
   151     def load(self):
       
   152         """
       
   153         Loads the session data and returns a dictionary.
       
   154         """
       
   155         raise NotImplementedError