Referer-checking view decorators

 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
from django.core.exceptions import PermissionDenied

def referer_matches_hostname(*netlocs):
    """
    Decorator for views that checks that if the request's HTTP_REFERER matches
    the supplied string. Failure raises a PermissionDenied exception. If
    multiple arguments are supplied the decorator will try to match any of
    them.
    """
    def _dec(view_func):
        def _check_referer(request, *args, **kwargs):
            import urlparse
            referer = request.META.get('HTTP_REFERER', '')
            referer_netloc = urlparse.urlparse(referer).netloc
            if referer_netloc in netlocs:
                return view_func(request, *args, **kwargs)
            raise PermissionDenied()
        _check_referer.__doc__ = view_func.__doc__
        _check_referer.__dict__ = view_func.__dict__        
        return _check_referer
    return _dec

def referer_matches_re(regex):
    """
    Decorator for views that checks that if the request's HTTP_REFERER matches
    the supplied regex pattern. Failure raises a PermissionDenied exception.
    """
    import re
    regex = re.compile(regex)
    def _dec(view_func):
        def _check_referer(request, *args, **kwargs):
            referer = request.META.get('HTTP_REFERER', '')
            if regex.match(referer):
                return view_func(request, *args, **kwargs)
            raise PermissionDenied()
        _check_referer.__doc__ = view_func.__doc__
        _check_referer.__dict__ = view_func.__dict__        
        return _check_referer
    return _dec

from django.contrib.sites.models import Site
local_referer_only = referer_matches_hostname(str(Site.objects.get_current()))
## Same, but using referer_matches_re:
# regex = r'^https?://%s/.*' % Site.objects.get_current()
# local_referer_only = referer_matches_re(regex)
local_referer_only.__doc__ = (
    """
    Decorator for views that checks that if the request's HTTP_REFERER matches
    the current site. If not, a PermissionDenied exception is raised.
    """
)

Comments

derivin (on April 15, 2007):

One minor enhancement:

def referer_matches_hostname(*netlocs):
...
        if referer_netloc in netlocs:

This will allow for multiple netloc's which can be easier than a regexp which may end up looking like '(netloc1|netloc2)' otherwise.

#

robbie (on April 15, 2007):

Thanks, derivin... I've updated the snippet accordingly.

#

(Forgotten your password?)

You may use Markdown syntax here, but raw HTML will be removed.