| 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 | | |
| 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 | |
| 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 {} |