示例#1
0
    def __init__(self, user, remote_addr):
        self.request_time = time.time()
        self.user = user
        self.cli = ThrottleClient()
        self.remote_addr = remote_addr

        # Separately caching user name, because str(user) yields an unwieldy
        # repr of the User class.
        self.user_name = str(user) if user is None else user.name
 def __init__(self, user, key):
     self.request_time = time.time()
     self.user = user
     self.cli = ThrottleClient()
     self.key = key
class LoginThrottle(object):
    login_lock_timeout = int(
        config.get('ckanext.security.lock_timeout', 60 * 15))
    login_max_count = int(config.get('ckanext.security.login_max_count', 10))
    count = 0
    last_failed_attempt = 0

    def __init__(self, user, key):
        self.request_time = time.time()
        self.user = user
        self.cli = ThrottleClient()
        self.key = key

    def _check_count(self):
        return self.count >= self.login_max_count

    def _check_time_since_last_attempt(self, last_attempt):
        return self.request_time - float(
            last_attempt) < self.login_lock_timeout

    def get(self):
        value = self.cli.get(self.key)
        if value is not None:
            return json.loads(value)
        return {}

    def reset(self):
        value = self.get()
        value['count'] = 0
        self.cli.set(self.key, json.dumps(value))

    def increment(self):
        value = self.get()
        # An email will be sent once the count has reached login_max_count, so we
        # will only increment this counter until login_max_count + 1. Otherwise,
        # the user would be locked out for another `login_lock_timeout` minutes
        # whenever he/she tries to login again.
        if self.count < self.login_max_count + 1:
            value.update({
                'count': self.count + 1,
                'last_failed_attempt': self.request_time,
            })
            self.cli.set(self.key, json.dumps(value))

    def needs_lockout(self):
        if self.user is not None and self.count == self.login_max_count:
            log.info("%s locked out by brute force protection" %
                     self.user.name)
            try:
                notify_lockout(self.user)
                log.debug("Lockout notification for user %s sent" %
                          self.user.name)
            except Exception as exc:
                msg = "Sending lockout notification for %s failed"
                log.exception(msg % self.user.name, exc_info=exc)
        return False

    def check_attempts(self):
        value = self.get()
        in_possible_lockout_window = self._check_time_since_last_attempt(
            value.get('last_failed_attempt', 0))
        self.count = value.get('count', 0) if in_possible_lockout_window else 0
        if self._check_count():
            return self.needs_lockout()

    def is_locked(self):
        if self.check_attempts() is False:
            self.increment(
            )  # Increment so we only send an email the first time around
            return True
        return False
示例#4
0
class LoginThrottle(object):
    # Login throttling lock period - 15 min
    login_lock_timeout = int(
        config.get('ckanext.security.lock_timeout', 60 * 3))
    # Login throttling attempt limit - 3 times
    login_max_count = int(config.get('ckanext.security.login_max_count', 3))
    count = 0

    def __init__(self, user, remote_addr):
        self.request_time = time.time()
        self.user = user
        self.cli = ThrottleClient()
        self.remote_addr = remote_addr

        # Separately caching user name, because str(user) yields an unwieldy
        # repr of the User class.
        self.user_name = str(user) if user is None else user.name

    def _check_count(self):
        return self.count >= self.login_max_count

    def _check_time(self, last_attempt):
        return self.request_time - float(
            last_attempt) < self.login_lock_timeout

    def get(self):
        value = self.cli.get(self.remote_addr)
        if value is not None:
            return json.loads(value)
        return {}

    def reset(self):
        value = self.get()
        if self.user_name in value:
            del value[self.user_name]
        self.cli.set(self.remote_addr, json.dumps(value))

    def increment(self):
        value = self.get()
        # An email will be sent once the count has reached login_max_count, so we
        # will only increment this counter until login_max_count + 1. Otherwise,
        # the user would be locked out for another `login_lock_timeout` minutes
        # whenever he/she tries to login again.
        if self.count < self.login_max_count + 1:
            value.update({
                self.user_name:
                "%s:%s" % (self.count + 1, self.request_time)
            })
            self.cli.set(self.remote_addr, json.dumps(value))

    def needs_lockout(self, cache_value):
        count, last_attempt = cache_value.split(':')
        self.count = int(count) if self._check_time(last_attempt) else 0
        if self._check_count():
            if self.user is not None and self.count == self.login_max_count:
                log.info("%s locked out by brute force protection" %
                         self.user.name)
                try:
                    notify_lockout(self.user, self.remote_addr)
                    log.debug("Lockout notification for user %s sent" %
                              self.user.name)
                except Exception as exc:
                    msg = "Sending lockout notification for %s failed"
                    log.exception(msg % self.user.name, exc_info=exc)
            return False

    def check_attempts(self):
        cached = self.get().get(self.user_name, None)
        if cached is not None:
            return self.needs_lockout(cached)