让 Python 更快地进行验证,python进行验证,未经许可,禁止转载!英文


本文由 编橙之家 - zer0Black 翻译,果果夫斯基 校稿。未经许可,禁止转载!
英文出处:stormpath.com。欢迎加入翻译组。

你知道什么事情最捉急么?慢的网站。

不幸的是,验证过程中某些特定部分就应该是缓慢的。这似乎违反直觉,但是验证过程中的慢速是保证安全的很大一部分。

本文介绍 Python 中的验证过程(不仅仅是散列法),还有如何在不降低安全性的条件下提高 Python 的验证速度。

我将带你读一下 Python 伪代码,并教你如何保证验证系统尽可能快而需要掌握的知识。

密码散列法很慢

当用户在网站上注册时,给了密码——最好的方法是在存储之前去散列用户密码。这意味着你可以用一个散列算法,比如 bcrypt 或 scrypt 这样,可以把一个密码字符串翻译为不能被反向破解的胡言乱语。

一旦用了散列法,就没有办法回复原始密码了。

有个重要的点:强大的散列函数,比如 bcrypt 和 scrypt ,是命中注定般的慢啊

散列法需要更多的 CPU、RAM 和时间用来计算,这意味着一个攻击者会需要花费更长的时间来暴力破解一个密码。

现在,假设你已经黑入了数据库,还有可以访问全部用户密码的散列。

也可以说是有10个 bcrypt 散列。

如果想要找到密码,你只能去:暴力破解它们。

想做到这点,你会写一些代码来遍历所有可能的密码组合(在下面的例子中我用 PyPI 中的brute库):

Python
$ pip install brute

# crack.py
from brute import brute

HASH_TO_CRACK = 'xxx'

for pw in brute(length=8):
    if HASH_TO_CRACK == bcrypt(pw):
        print 'Password is:', pw
        break

上面的例子中,我们会遍历所有8个字母或以下的可能密码,并试图去暴力破解它。

每次新生成一个可能的密码,通过 bcrypt 函数运行,得到散列,将它和你已经黑了的密码散列比较。如果你得到了一对儿,意味着你已经成功暴力破解了用户密码!

但是有个重点:bcrypt 和 scrypt 会花很长时间去计算,占用很多资源。

因为bcrypt和scrypt在数学意义上计算很慢,攻击者会因为占用太多计算机资源而很艰难地花费时间来暴力破解。

因此,我们现在理解了散列的原理,以及为什么时间密集——我们来讨论一下验证。

:如果你对于了解密码安全有兴趣,你也许会想要去读篇写了有点时间的文章对于密码安全的正确方法——是个好的阅读材料。如果你想更加了解,看看这个.

如何进行验证工作

当用使用传统的方法注册或登录网站时,你需要散列他们的密码,然后存储到数据库或与数据库中的值进行比较——然后发生了什么?你要记住,用户不是有一个会话ID就是有某种API秘钥。

看看这些伪代码:

Python
# register.py
user = User('r@rdegges.com', 'hithere!123')
user.save()     # save this user to the database

# Create a new session cookie in the browser, which holds the user ID.
session.create('session', user.id)

这个办法的思路是用户 ID 存储到用户的浏览器缓存中,下一次用户请求你网站时,用户浏览器就发送缓存中的用户 ID 给你的服务器,并允许你浏览用户账号下的信息,而不需要再次输入邮件地址或密码。

再看看这些伪代码:

Python
# views.py
user = User.find(id=session)

正如你料想的——通过 ID 查询用户账号是非常快的(密码不散列是必要的)。

因此——这就意味着初始创建账户和登录密码的过程较慢——剩下的就都很快了!

我们继续。

优化速度

一旦用户数据请求网站的每个页面,数据就要接收的非常频繁。

如过你使用了 Postgres  或  MySQL 之类的数据库,这就意味着你的网站如果有100个用户,那你每秒要查询数据库的users表数百次。

如果你的网站还需要做其他事,你可能忍不了这么慢的网页加载。

你可以做什么来提速呢?缓存!

缓存是速度和性能问题的解决方案——提升访问你网站的速度时,让用户数据快速加载速度的有效方法之一。

这种方法超简单:存储键值对到持久化存储中,用户ID作为键,用户的账户数据作为散列值。

这很有用,因为下次用户请求你网页时,就可以发送会话缓存,而不是通过数据库查询账户,你也可以直接从内存数据库缓存查询这些信息。

对于缓存,你也许更想要存储数据到 memcached 或 redis 之类的缓存系统中,令人开心的是,python都有对应的库

在伪代码里,你可以这么做:

Python
if session:
    user = cache.get(session)

    # If no user was found in the cache, try querying the database directly.
    if not user:
        user = User.get(id=session)

实现

如果你用了 Django之类的web框架,那用(框架)内置的校验系统就可以很容易的完成这篇文章提及的所有内容。

如果你用了另一个框架/工具,你也许想到google搜寻一下相关库。不管你用什么工具,本文的几个典型选项都能帮到你。

最后,如果你在用 Python / Flask / Django,并且想要得到关于用户存储和安全最全、最好的实践,你可以看看我们的开发者服务 Stormpath。

我们的服务为你存储用户账户和用户数据,负责处理密码散列、加密、数据安全、最好的实践和其他的所有。

可以免费用于大多数应用,也有轻松整合到Python、Flask 和 Django 应用。

我们最新发布的 Python 库中包含了内建的支持内存数据库、memcached 和 redis 缓存,以确保总是尽可能快速访问你的网站。

如果你想用Stormpath,你可以从下面地址得到我们的库:

  • python-stormpath
  • flask-stormpath
  • django-stormpath

评论关闭