限制django模型使用缓存的功能:这是个好主意还是坏主意



我的django项目有一个用户模型,它可以在网站上做一些事情,比如发布内容、评论、编辑等。我想办法限制每天的操作次数,以防止垃圾邮件,我决定不去处理与日期时间相关的烦人的事情,而是将数据存储到缓存(memcached)中,为其创建一个功能。

编辑:找到了一个解决方案:

我使用旧的实现,缓存每天的帖子数量,并将一天设置为超时。但也有一个celeniasynccron作业,它每天检查和擦除一次选定的缓存键。

所以我使用了下面的原始代码,加上这个:

from django.core.cache import cache
from lib.cache_keys import daily_count_key
from django.contrib.auth.models import User
@periodic_task(run_every=crontab(hour='*/24')) # AKA run once a day
def wipeDailyLimits():
users = User.objects.all()
for user in users:
cache.delete(daily_count_key("modelone", user))
cache.delete(daily_count_key("modeltwo", user))
cache.delete(daily_count_key("modelthree", user))

示例:

def post_entry(request):
# post the entry
daily_post_count = cache.get(request.user.id + "entrycount")
if daily_post_count >= 5:
return error
if daily_post_count is None:
daily_post_count  = 1
if daily_post_count < 5:  # 5 posts per day
daily_post_count += 1
cache.set(request.user.id + "entrycount", daily_post_count , 86400)
# Unix one day time out
# return regular

到目前为止,这个策略看起来不错,一切都很好,但我想知道用户是否有漏洞或技巧可以用来破坏这个系统?如果是这样的话,大多数人是如何处理django的限制的?

感谢

两件事;

  • 如果一个用户同时发布多个帖子,他们可能会完成这些帖子,因为不止一个进程可以读取计数,两个进程都会增加每日post_count,并且都会存储旧值+1(如果它们相互追跑,最后会存储旧的值+2)不太可能是个问题。

  • 你的计数并没有完全按照你的意愿重置,因为你每次保存帖子时都会重置超时。如果我发了一篇帖子,然后23小时后又发了一次,然后23个小时后再发一次,计数将是3,但已经过去了46个小时。将计数器设置为0的唯一方法是等待24小时而不发布,否则它将永远不会减少。很可能会惹恼用户,如果他们不能发布,如果他们应该能够:)

我建议使用不同的方法。你目前的方法意味着,即使在非垃圾邮件之后,用户也不知道他的帖子是否会被传播。相反,如果您想进行限制,在呈现页面/站点之前,请添加一个中间件,该中间件执行您想要约束的任何内容的count(),并向您的HTTPResponse添加一个声明daily_limt_exceeeded=True的标志。通过这种方式,您可以显示适当的基于标志的警告消息,并禁止用户在达到限制后发帖。

如果你愿意,你可以使用Django评论框架在你的网站上发表评论,它有一些垃圾邮件保护:

评论表单上的注释

评论系统使用的表单具有一些重要的反垃圾邮件属性,您应该了解这些属性:它包含许多隐藏字段,这些字段包含时间戳、注释应附加到的对象的信息,以及用于验证这些信息的"安全哈希"。如果有人篡改了这些数据——评论垃圾邮件发送者会尝试这样做——评论提交将失败。如果要呈现自定义注释表单,则需要确保传递这些值时保持不变。时间戳用于确保"回复攻击"不会持续很长时间。如果用户在请求表单和发布评论之间等待太久,他们的提交将被拒绝

评论表单包括一个"蜜罐"字段。这是一个陷阱:如果在该字段中输入了任何数据,评论将被视为垃圾邮件(垃圾邮件发送者通常会自动填写所有字段,试图进行有效提交)。

默认表单用一段CSS隐藏此字段,并用警告字段进一步标记它;如果您将注释表单与自定义模板一起使用,您应该确保也这样做。评论应用程序还依赖于Django提供的更通用的跨站点请求伪造保护。如文档中所述,最好使用CsrfViewMiddleware。但是,如果您没有使用它,则需要在包括注释表单的任何视图上使用csrf_protect装饰器,以便这些视图能够输出csrf令牌和cookie。

找到了一个解决方案,该解决方案具有这两种功能的优点,但更易于实现。我使用旧的实现,缓存每天的帖子数量,并将一天设置为超时。但也有一个celeniasynccron作业,它每天检查和擦除一次选定的缓存键。

用户会知道他们受到了限制,因为只有变量被传递到模板中。

无论如何,感谢你们的帮助!

最新更新