Welcome, guest | Sign In | My Account | Store | Cart
NOTE: Recipes have moved! Please visit GitHub.com/activestate/code for the current versions.

This is a very simple session handling example that uses plain Python CGI (tested only under Python 2.2+). Its goal is to show how cookies are set via HTTP and how easily they can be used for session management.

Python, 97 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#!/usr/bin/python2.2
"""
A very simple Session Handling example
using plain Python CGI (tested only under Python 2.2+)

License: GPL 2; share and enjoy!
Author: Jonas Galvez <jonasgalvez@gmail.com>
Contributor: Patrick Hall <pathall@gmail.com>

Usage: /script.cgi?start=1
"""

import cgitb; cgitb.enable()
import sys, os, cgi, pickle
from Cookie import SimpleCookie

class form(dict):
    def __init__(self, fields):
        dict.__init__(self, fields)
        for k, v in self.items(): self[k] = v.value

form = form(cgi.FieldStorage())

# hard-coded index numbers
# to make it easier to pass to functions
questions = (
    (0, "What's your name?"),
    (1, "How old are you?"),
    (2, "Where are you from?")
)
#questions = [(i, q.strip()) for i, q in enumerate(open('questions.txt').readlines())]

def generate_hash():
    import sha, time
    return sha.new(str(time.time())).hexdigest()

def print_headers(headers):
    for k, v in headers.items():
        sys.stdout.write('%s: %s\n' % (k, v))
    sys.stdout.write('\n')

def print_form(question):
    form_template = """<html><body><form action="%(script)s" method="POST">
    %(question)s:<br /><input type="hidden" name="question_id" value="%(id)s" />
    <input type="text" name="answer" /><input type="submit" /></form></body></html>"""
    id, question = question
    script = os.environ.get('SCRIPT_NAME', sys.argv[0])
    sys.stdout.write(form_template % locals())

def print_result(questions):
    sys.stdout.write('<html><body>')
    for i, q, a in questions:
        sys.stdout.write('<p>Question: %s<br />Answer:%s</p>' % (q[1], a))
    sys.stdout.write('</body></html>')

if not os.path.exists('.sessions'):
    os.mkdir('.sessions')

def main():

    if not form.has_key('start'):

        sid = SimpleCookie(os.environ['HTTP_COOKIE'])['sid'].value
        id, answer = form['question_id'], form['answer']

        if os.path.exists(os.path.join('.sessions', sid)):
            session_file = open(os.path.join('.sessions', sid), 'rb')
            session_obj = pickle.load(session_file)
            session_file.close()
        else:
            session_obj = {}
            session_obj['questions'] = []

        session_obj['questions'].append((id, questions[int(id)], answer))
        session_file = open(os.path.join('.sessions', sid), 'wb')
        pickle.dump(session_obj, session_file, 1)
        session_file.close()

        if len(session_obj['questions']) == len(questions):
            print_headers({'Content-type':'text/html'})
            print_result(session_obj['questions'])
        else:
            headers = {}
            headers['Content-type'] = 'text/html'
            headers['Set-Cookie'] = 'sid=%s;' % sid
            print_headers(headers)
            print_form(questions[int(id)+1]) # funky

    else:
        headers = {}
        headers['Content-type'] = 'text/html'
        headers['Set-Cookie'] = 'sid=%s;' % generate_hash()
        print_headers(headers)
        print_form(questions[0])

if __name__ == '__main__':
    main()

Please note that this is a totally insecure script. There's no explicit timeout, no user IP verification etc. Also, I'm using an extremely simple cookie to hold the user's session id (eg. no path specified). Plus, session data is stored in simple files using pickle.

6 comments

the_murple 12 years, 11 months ago  # | flag

bad style. Using the same name for the class and the instance is confusing:

form = form(cgi.FieldStorage())
<pre>

</pre>

Henryk Gerlach 12 years, 11 months ago  # | flag

Don't use that Session ID in Real live. generate_hash() is quite insecure: The returned hash only depends on time which can be easily guessed.

Nice example anyway...

colin 12 years, 11 months ago  # | flag

Not safe. Asside from the obvious security implications of using un-signed cookies there is another problem with this example: There's no locking to stop multiple requests accessing the same session file. It's very easy to get corrupt sessions with code like this.

activestate_com 12 years, 4 months ago  # | flag

nice, but... I have made a session handling with Cookies + SQL. You can find the source on my Homepage:

http://www.jensdiemer.de/?Python

Guido van Rossum 11 years, 8 months ago  # | flag

Guessing time? > The returned hash only depends on time which can be easily guessed.

Up to the millisecond? Remember time.time() returns a float!

Sunjay Varma 6 years, 9 months ago  # | flag

I wrote my own, more sophisticated recipe on Session handling. Not sure if my recipe is much better, but it has certain things like file locking and such that should prove quite useful. Here it is: http://code.activestate.com/recipes/577524-python-sessions/?in=lang-python