Permalink
Browse files

Import cookieless sessions patch.

  • Loading branch information...
1 parent 3104878 commit a043a1215054f57fbb91cd24e5b5a968da0f636a Michael Gorven committed Jan 15, 2010
Showing with 47 additions and 2 deletions.
  1. +47 −2 web/session.py
View
49 web/session.py
@@ -3,7 +3,7 @@
(from web.py)
"""
-import os, time, datetime, random, base64
+import os, time, datetime, random, base64, sys
try:
import cPickle as pickle
except ImportError:
@@ -15,6 +15,12 @@
import sha
sha1 = sha.new
+try:
+ from BeautifulSoup import BeautifulSoup, Tag
+ from urlparse import urlsplit, urlunsplit
+except ImportError:
+ pass
+
import utils
import webapi as web
@@ -31,6 +37,7 @@
'ignore_change_ip': True,
'secret_key': 'fLjUfxqXtfNoIldA0A0J',
'expired_message': 'Session expired',
+ 'cookieless': False,
@foxbunny
foxbunny Jan 19, 2010

A small aesthetic correction, if I may. I think it'd look better if you say use_cookies = True here.

})
class SessionExpired(web.HTTPError):
@@ -56,16 +63,24 @@ def _processor(self, handler):
self._load()
try:
- return handler()
+ response = handler()
finally:
self._save()
+ if self._config.cookieless:
+ response = self._add_session(response)
+
+ return response
+
def _load(self):
"""Load the session from the store, by the id from cookie"""
cookie_name = self._config.cookie_name
cookie_domain = self._config.cookie_domain
self.session_id = web.cookies().get(cookie_name)
+ if self._config.cookieless and not self.session_id:
+ self.session_id = web.input().get(cookie_name)
+
# protection against session_id tampering
if self.session_id and not self._valid_session_id(self.session_id):
self.session_id = None
@@ -109,6 +124,36 @@ def _save(self):
self.store[self.session_id] = dict(self)
else:
web.setcookie(cookie_name, self.session_id, expires=-1, domain=cookie_domain)
+
+ def _is_relative(self, url):
+ if url is None: return True
+ split = urlsplit(url)
+ return split[0] == '' and split[1] == ''
+
+ def _add_session(self, response):
+ cookie_name = self._config.cookie_name
+
+ # Only process response if client didn't provide a session cookie
+ if not web.cookies().get(cookie_name) and 'BeautifulSoup' in sys.modules:
@foxbunny
foxbunny Jan 19, 2010

Beautiful soup is a requirement for this to work?

+ soup = BeautifulSoup(str(response))
+
+ # Add hidden input fields to forms
+ for form in soup.findAll('form', action=lambda(x): self._is_relative(x)):
+ input = Tag(soup, "input", [("type", "hidden"), ("name", cookie_name), ("id", cookie_name), ("value", self.session_id)])
+ form.insert(0, input)
+
+ # Add query parameters to relative links
+ param = cookie_name + '=' + self.session_id
+ for a in soup.findAll('a', href=lambda(x): self._is_relative(x)):
+ parts = list(urlsplit(a['href']))
+ if len(parts[3]) == 0:
+ parts[3] = param
+ else:
+ parts[3] += '&' + param
+ a['href'] = urlunsplit(parts)
+
+ return str(soup)
+ return response
def _generate_session_id(self):
"""Generate a random id for session"""

7 comments on commit a043a12

@mgorven
Owner

For cookieless sessions, yes (it's not required if you don't want to use cookieless sessions). I can replace it with a different HTML parser if necessary.

@foxbunny

I think it'd be more prudent to get it working with python's standard library.

@mgorven
Owner

The tools in stdlib aren't really suitable for working with HTML. HTMLParser is very low level, and the XML tools won't handle HTML. I think the options to choose from are BeautifulSoup, html5lib, and lxml.html.

@foxbunny

I see. I'll look into the docs and see if I can come up with something. I'm interested in cookie-less solution, but I don't like the idea of having BeautifulSoup in there if I'm not using it elsewhere.

@mgorven
Owner

That's a bit misleading, because even if cookieless sessions are enabled it still prefers cookies.

@foxbunny

I see. Do you have a way to completely disable cookies?

@mgorven
Owner

No, because this approach has security implications and so should really be a last resort. It is of course possible to add, but I don't see why one wouldn't want to use cookies if they are available.

Please sign in to comment.