Here is a modified version for handling epxired ip log.

def limitAttemped(func):
    max_attempted = tg.config.get('identity.max_attempted', 10)
    expired_delay = tg.config.get('identity.expired_delay', 1800)
    log = logging.getLogger('turbogears.identity')
    def callee(*args, **kwargs):
        result = func(*args, **kwargs)
        ip = getIpAddress()
        ipLog = model.IPLog.get(ip)
        if ipLog is not None:
            expired = ipLog.updated + datetime.timedelta
(seconds=expired_delay)
            if datetime.datetime.now() > expired:
                db.session.delete(ipLog)
                db.session.flush()
                ipLog = None
                log.info('Delete expired ip log %s', ip)
        if tg.identity.current.anonymous and
tg.identity.was_login_attempted():
            ipLog = model.IPLog.logIp(ip)
        if ipLog is not None and ipLog.times > max_attempted:
            cherrypy.request.identity_exceed_max_attempted = True
            tg.identity.current.logout()
            log.warning('Login failed exceed limit times from %s', ip)
        return result
    return callee

Victor wrote:
> Hi,
>
> I want to limit times of failed login. Here is the recipe I write.
>
> #### the model
> class IPLog(Entity):
>     """A table for logging ip of user who try to login with wrong
> password
>
>     """
>     using_options(tablename='ip_log')
>     using_table_options(mysql_engine='MEMORY')
>
>     # which ip
>     ip = Field(String(64), primary_key=True, nullable=False)
>     # how many mistake he made
>     times = Field(Integer, nullable=False, default=0)
>     # last login failed date time
>     updated = Field(DateTime, default=datetime.now, index=True)
>
>     @classmethod
>     def logIp(cls, ip):
>         ip = unicode(ip)
>         log = cls.query.get(ip)
>         if log is None:
>             log = cls(ip=ip, times=0)
>         log.times += 1
>         log.updated = func.current_timestamp()
>         return log
>
> # before root controller
>
> def getIpAddress():
>     return cherrypy.request.headers.get('X-Forwarded-For',
>         cherrypy.request.remote_addr)
>
> def limitAttemped(func):
>     max_attempted = tg.config.get('identity.max_attempted', 10)
>     def callee(*args, **kwargs):
>         result = func(*args, **kwargs)
>         ip = getIpAddress()
>         if tg.identity.current.anonymous and
> tg.identity.was_login_attempted():
>             log = model.IPLog.logIp(ip)
>         else:
>             log = model.IPLog.get(ip)
>         if log is not None and log.times > max_attempted:
>             log = logging.getLogger('turbogears.identity')
>             cherrypy.request.identity_exceed_max_attempted = True
>             tg.identity.current.logout()
>             log.warning('Login failed exceed limit times from %s', ip)
>         return result
>     return callee
>
> tg.identity.visitor.IdentityVisitPlugin.record_request = \
>     limitAttemped
> (tg.identity.visitor.IdentityVisitPlugin.record_request)
>
> ### login method
>
>     @tg.expose(template="radioweb.templates.login")
>     def login(self, forward_url=None, *args, **kw):
>
>         if getattr(cherrypy.request, 'identity_exceed_max_attempted',
> False):
>             flash.error(
>                 _('Sorry, you attempted to login exceed the limit
> times. '
>                   'Please try later.')
>             )
>             tg.redirect(tg.url('/'))
>
>
> It works, but however, I am wondering, is there any thing I did not
> considered? Is that safe enough? If it is safe enough, I will post it
> to wiki of turbogears.
>
> Thanks.
> Victor Lin.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"TurboGears" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to 
[email protected]
For more options, visit this group at 
http://groups.google.com/group/turbogears?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to