0

Is there an easy way to limit the number of times a view can be accessed by a given IP address per day/week? A simplified version of the technique used by some booksellers to limit the number of pages of a book you can preview?

There's only one view that this limit need apply to--i.e. it's not a general limit--and it would be nice if I could just have a variable overlimit in the template context. The solution need not be terribly robust, but limiting by IP address seemed like a better idea than using a cookie.

I've looked into the session middleware but it doesn't make any references to tracking IP addresses as far as I can tell.

Has anyone encountered this problem?

ariddell
  • 3,413
  • 34
  • 32

3 Answers3

3

The solution I came up with harnessed the django-hitcount app and a "wrapping" of the original view. Luckily, I have an object (Page) that I can associate with the view I'm trying to limit, so the hitcount app works well (and mostly as intended).

The view I'm tracking is line_list -- so I called the new view to wrap it line_list_monitor and associated the original url for line_list with it. The new view is included below. If the IP in question is over the limit (20 views per week), I redirect to overlimit.html, else the original view just gets called like normal.

def line_list_monitor(request, character, pagenum):
    LIMIT_HITS = 20
    LIMIT_PERIOD = {'weeks': 1}
    obj, created = Page.objects.get_or_create(character=character, page=pagenum)
    obj_pk = obj.pk
    ctype = ContentType.objects.get_for_model(obj)
    hitcount, created = HitCount.objects.get_or_create(content_type=ctype,
                                                          object_pk=obj_pk)
    hit = Hit(session="",
              hitcount=hitcount,
              ip=get_ip(request),
              user_agent="")
    hit.save()
    period = datetime.datetime.utcnow() - datetime.timedelta(**LIMIT_PERIOD)
    count = hitcount.hit_set.filter(ip=get_ip(request),
                                    created__gte=period).count()
    if count > LIMIT_HITS:
        template = "overlimit.html"
        return render_to_response(template, context_instance=RequestContext(request))
    else:
        return line_list(request, character, page)
Community
  • 1
  • 1
ariddell
  • 3,413
  • 34
  • 32
0

The HttpRequest object has a META member dictionary, which has a REMOTE_ADDR member, so request.META["REMOTE_ADDR"] should get you the IP address in the view, which can then set overlimit in the context... Is that what you want?

Mike DeSimone
  • 41,631
  • 10
  • 72
  • 96
  • But I'll need to keep a running count. Right now I'm thinking this requires a new model to track view requests by IP... thought I might avoid this though. – ariddell Mar 04 '10 at 12:04
  • Just answering the question as posed. Any solution is going to need a per-IP or per-user model to be created to track the user. The kind of system you're talking about isn't terribly robust, and may be relatively easy to circumvent via proxies or dynamic IP assignments. Sessions are really meant to prevent the need for the user to present user Id and password for every single action they take, i.e. a convenience for both the user and site operator. If you try to use it to restrict the user, they will find a way around it. Also, if the page load fails, it can cheat the user. – Mike DeSimone Mar 04 '10 at 18:57
0

if you are able to define firewall (iptables/netfilter) on your server you can limit the access very easy. a tutorial how this is done can be found at debian administrator. this is an example how to secure the ssh-port, but you can use the same technique for http.

i have all of my servers "secured" like this, and i am very lucky with it.

keep in mind, that if you have ajax-functionality on your site you need much more requests/minute like on non-ajax sites allowed by the firewall

bmaeser
  • 982
  • 7
  • 13
  • So the firewall can limit the number of accesses to a certain range of web pages to a certain number per day per IP, while allowing unlimited access of the rest of the site? Sounds like deep packet inspection. – Mike DeSimone Mar 05 '10 at 13:52