21.2. CookiesHTTP, per se, is a stateless protocol, meaning that it retains no session state between transactions. Cookies, as specified by the HTTP 1.1 standard, let web clients and servers cooperate to build a stateful session from a sequence of HTTP transactions. Each time a server sends a response to a client's request, the server may initiate or continue a session by sending one or more Set-Cookie headers, whose contents are small data items called cookies. When a client sends another request to the server, the client may continue a session by sending Cookie headers with cookies previously received from that server or other servers in the same domain. Each cookie is a pair of strings, the name and value of the cookie, plus optional attributes. Attribute max-age is the maximum number of seconds the cookie should be kept. The client should discard saved cookies after their maximum age. If max-age is missing, then the client should discard the cookie when the user's interactive session ends. Cookies provide no intrinsic privacy or authentication. Cookies travel in the clear on the Internet and are vulnerable to sniffing. A malicious client might return cookies different from cookies previously received. To use cookies for authentication or identification, or to hold sensitive information, the server must encrypt and encode cookies sent to clients, and decode, decrypt, and verify cookies received back from clients. Encryption, encoding, decoding, decryption, and verification may all be slow when applied to large amounts of data. Decryption and verification require the server to keep some amount of server-side state. Sending substantial amounts of data back and forth on the network is also slow. The server should therefore persist most state data locally in files or databases. In most cases, a server should use cookies only as small, encrypted, verifiable keys that confirm the identity of a user or session, using DBM files or a relational database (both covered in Chapter 11) for session state. HTTP sets a limit of 2 KB on cookie size, but I suggest you normally use even smaller cookies. 21.2.1. The Cookie ModuleThe Cookie module supplies several classes, mostly for backward compatibility. CGI scripts normally use the following classes from module Cookie.
21.2.1.1. Cookie methodsAn instance c of SimpleCookie or SmartCookie supplies the following methods.
21.2.1.2. Morsel attributes and methodsAn instance m of class Morsel supplies three read/write attributes:
Instance m also supplies the following methods.
21.2.1.3. Using module CookieModule Cookie supports cookie handling in both client-side and server-side scripts. Typical usage is server-side, often in a CGI script (where you have no alternatives, to maintain session state, to the direct manipulation of cookies). The following example shows a simple CGI script using cookies: import Cookie, time, os, sys, traceback sys.stderr = sys.stdout try: # first, the script emits HTTP headers c = Cookie.SimpleCookie( ) c["lastvisit"]=str(time.time( )) print c.output( ) print "Content-Type: text/html" print # then, the script emits the response's body print "<html><head><title>Hello, visitor!</title></head> <body>" # for the rest of the response, the scripts gets and decodes the cookie c = Cookie.SimpleCookie(os.environ.get("HTTP_COOKIE")) when = c.get("lastvisit") if when is None: print "<p>Welcome to this site on your first visit!</p>" print "<p>Please click the 'Refresh' button to proceed</p>" else: try: lastvisit = float(when.value) except: print "<p>Sorry, cannot decode cookie (%s)</p>"%when.value print "</br><pre>" traceback.print_exc( ) else: formwhen = time.asctime(time.localtime(lastvisit)) print "<p>Welcome back to this site!</p>" print "<p>You last visited on %s</p>"%formwhen print "</body></html>" except: print "Content-Type: text/html" print print "</br><pre>" traceback.print_exc( ) Each time a client visits the script, the script sets a cookie encoding the current time. On successive visits, if the client browser supports cookies, the script greets the visitor appropriately. Module time is covered in "The time Module" on page 302. This example uses no cryptography or server-side persistence, since session state is small and not confidential. |