Source

django-doorkeeper / doorkeeper / middleware.py

# -*- coding: utf-8 -*-
# Creation date: 10.03.12

import datetime, hashlib
from django.http import Http404
from doorkeeper.models import BotRecord
from django.conf import settings
from utils import MemClient
try:
    from django.utils.timezone import now as django_now
except ImportError:
    django_now=datetime.datetime.now
import logging
log = logging.getLogger(__name__)

PATIENCE= getattr(settings,'DOORKEEPER_PATIENCE', 5)
MEMCACHE=getattr(settings,'DOORKEEPER_MEMCACHE', False)
TERM = getattr(settings,'DOORKEEPER_TERM', 1200)


class DoorkeeperMiddleware(object):
    def process_request(self, request):
        """
          Each request is investigated - overheads for suspicions
          If memcahed is used:
            overheads = md5-hash calculation + memcache.get request
          I think its a reasonable price
        """
        sagent = request.META.get('HTTP_USER_AGENT',"n/a")
        saddr = request.META.get('REMOTE_ADDR',"n/a")
        shash = "%s %s"% (saddr, sagent)
        dd=hashlib.md5()
        dd.update(shash)
        memhash=dd.hexdigest()
        memhash0= memhash+"0"

        if MEMCACHE:                                 # ####  path for MEMCACHED (fast)
            mc=MemClient(MEMCACHE)
            br=mc.get(memhash)
            if br is None:
                return                               # ==>> exit for 99.9% requests
            bd = mc.get(memhash0)
            if bd is not None and bd >PATIENCE:      # for massive attack bounce
                log.info("bd=%s > PATIENCE=%s"% (bd,PATIENCE))
                raise Http404
            now=django_now()
            if br.detention_upto:                    # check detention end time
                try:
                    if br.detention_upto> now:           # if it is a fresh banned client
                        log.info("Memcached, %s penalty %s, detention %s for %s" %
                                 (shash,br.penalty_count, br.detention_upto, request.path))
                        raise Http404()                  # ==>> bounce - it's active bad bot!
                    else:
                        if br.penalty_count > PATIENCE:  # for old banned client
                            br.penalty_count-=PATIENCE   # forgiving them partly
                            br.save()
                            mc.add(memhash,br,time=TERM*2)
                            bd=0
                            mc.set(memhash0,bd,time=TERM*2)
                        pass                             # ==>> it was a bad bot, maybe not now?
                except TypeError as er:
                    log.error("%s: %s > %s  %s" %(er,br.detention_upto,now,request.path))
                    return
        else:                                        # ### path for DB-driven (slow)
            try:
                br=BotRecord.objects.get(bot_hash=shash) # if client exists in BotRecords
                now=django_now()
                if br.detention_upto:                    # check detention end time
                    try:
                        if br.detention_upto> now:           # if it is a fresh banned client
                            raise Http404()                  # bounce - it's active bad bot!
                        else:
                            if br.penalty_count > PATIENCE:  # for old banned client
                                br.penalty_count-=PATIENCE   # forgiving them partly
                                br.save()                    # ==>> it was a bad bot, maybe not now?
                            pass
                    except TypeError as er:
                        log.error("%s: %s > %s  %s" %(er,br.detention_upto,now,request.path))
                        return
            except BotRecord.DoesNotExist:               # ==>> exit for most requests
                pass
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.