ContributedMiddleware: SSLMiddleware.2.py

File SSLMiddleware.2.py, 2.8 KB (added by sjzabel@…, 9 years ago)

Contains an urls.py based SSL approach

Line 
1"""
2SSL Middleware
3Stephen Zabel
4
5This middleware answers the problem of redirecting to (and from) a SSL secured path
6by stating what paths should be secured in urls.py file. To secure a path, add the
7additional view_kwarg 'SSL':True to the view_kwargs.
8
9For example
10
11urlpatterns = patterns('some_site.some_app.views',
12    (r'^test/secure/$','test_secure',{'SSL':True}),
13     )
14
15All paths where 'SSL':False or where the kwarg of 'SSL' is not specified are routed
16to an unsecure path.
17
18For example
19
20urlpatterns = patterns('some_site.some_app.views',
21    (r'^test/unsecure1/$','test_unsecure',{'SSL':False}),
22    (r'^test/unsecure2/$','test_unsecure'),
23     )
24
25Gotcha's : Redirects should only occur during GETs; this is due to the fact that
26POST data will get lost in the redirect.
27
28A major benefit of this approach is that it allows you to secure django.contrib views
29and generic views without having to modify the base code or wrapping the view.
30
31This method is also better than the two alternative approaches of adding to the
32settings file or using a decorator.
33
34It is better than the tactic of creating a list of paths to secure in the settings
35file, because you DRY. You are also not forced to consider all paths in a single
36location. Instead you can address the security of a path in the urls file that it
37is resolved in.
38
39It is better than the tactic of using a @secure or @unsecure decorator, because
40it prevents decorator build up on your view methods. Having a bunch of decorators
41makes views cumbersome to read and looks pretty redundant. Also because the all
42views pass through the middleware you can specify the only secure paths and the
43remaining paths can be assumed to be unsecure and handled by the middleware.
44
45This package is inspired by Antonio Cavedoni's SSL Middleware
46"""
47
48__license__ = "Python"
49__copyright__ = "Copyright (C) 2007, Stephen Zabel"
50__author__ = "Stephen Zabel"
51
52
53from django.conf import settings
54from django.http import HttpResponseRedirect, get_host
55
56SSL = 'SSL'
57
58class SSLRedirect:
59    def process_view(self, request, view_func, view_args, view_kwargs):
60        if SSL in view_kwargs:
61            secure = view_kwargs[SSL]
62            del view_kwargs[SSL]
63        else:
64            secure = False
65
66        if not secure == request.is_secure():
67            return self._redirect(request, secure)
68
69    def _redirect(self, request, secure):
70        protocol = secure and "https" or "http"
71        newurl = "%s://%s%s" % (protocol,
72                                                                                  get_host(request),
73                                                                                  request.get_full_path())
74
75        if settings.DEBUG and request.method == 'POST':
76            raise RuntimeError, \
77"""Django can't perform a SSL redirect while maintaining POST data.
78Please structure your views so that redirects only occur during GETs."""
79
80        return HttpResponseRedirect(newurl)
Back to Top