Commits

imbolc committed 18d9807

csrf protection middleware

Comments (0)

Files changed (2)

pysi/exceptions.py

 
 class BasicAuth(Exception):
     def __init__(self):
-        self.res = wsgi.Response('Authorization Error', 
+        self.res = wsgi.Response('Authorization Error',
             code=401, content_type='text/plain',
             headers={'WWW-Authenticate' : 'Basic realm="Enter password"'},
         )

pysi/middlewares.py

 # -*- coding: utf-8 -*-
 import marshal
 import base64
+import uuid
 
 from pysi import cfg
 from util import anticache_headers
+from wsgi import get_error_page
 
 
 cfg.set_defaults(
     BASIC_AUTH_PREFIXES = ('/', ),
     ANTICACHE_PREFIXES = ('/', ),
+    CSRF_TOKEN_COOKIE_NAME = 'csrf',
+    CSRF_TOKEN_POST_NAME = 'csrf',
+    CSRF_TOKEN_TEMPLATE_NAME = 'csrf',
+    CSRF_EXEMPT_PREFIXES = (),
 )
 
+
+class CSRF(object):
+    def process_request(self, rq):
+        token = rq.COOKIES.get(cfg.CSRF_TOKEN_COOKIE_NAME)
+        if token:
+            token = token.value
+        if rq.method == 'POST':
+            if not rq.path.startswith(cfg.CSRF_EXEMPT_PREFIXES):
+                if token != rq.POST.get(cfg.CSRF_TOKEN_POST_NAME):
+                    res = get_error_page(rq, 403)
+                    if token is not None:
+                        res.delete_cookie(cfg.CSRF_TOKEN_COOKIE_NAME)
+                    raise res
+        rq.context[cfg.CSRF_TOKEN_TEMPLATE_NAME] = token or uuid.uuid4().hex
+
+    def process_response(self, rq, res):
+        if cfg.CSRF_TOKEN_COOKIE_NAME not in rq.COOKIES:
+            res.set_cookie(cfg.CSRF_TOKEN_COOKIE_NAME,
+                    rq.context[cfg.CSRF_TOKEN_TEMPLATE_NAME])
+
+
 class BasicAuth(object):
     def process_request(self, rq):
         if rq.path.startswith(cfg.BASIC_AUTH_PREFIXES):
         elif rq._clear_flashes:
             res.delete_cookie(cfg.FLASH_COOKIE_NAME)
 
-    
 
+