存储盐渍令牌和令牌比较

时间:2016-10-04 17:28:13

标签: python django

我生成一个由单个使用令牌组成的URL,并通过电子邮件将其发送给用户。用户应单击此链接并重定向到将验证令牌并执行某些操作的页面。

在数据库方面,我存储此令牌(出于安全原因,哈希和盐渍)。问题是我在验证令牌方面遇到了一些困难,因为我存储它的方式,我不能为同一令牌生成相同的盐。因此,我无法将这种盐与我储存的盐进行比较。

# Retrieving or creating object usertokens
usr, created = UserToken.objects.get_or_create(email=email)
# Adding a new token
token = uuid.uuid4().hex
usr.token = make_password(token) # Stores in the local database the salted and hashed token
usr.save()

我使用的make_password方法在django.contrib.auth.hashers中定义。

通过使用此方法,我无法从同一令牌生成两次相同的盐。

>>> token = 'test'
>>> enc_token1 = make_password(token)
>>> enc_token2 = make_password(token)
>>> enc_token1 == enc_token2
False

然而,这并没有帮助我从我的数据库中检索对应于令牌的条目,我无法验证它。

1 个答案:

答案 0 :(得分:1)

使用两个散列和盐渍标记的简单字符串相等检查将不起作用。 Django docs for password managementdjango.contrib.auth.hashers命名空间中提供了一个非常简单的方法,可以为您处理所有这些:

>>> token = 'test'
>>> enc_token1 = make_password(token)
>>> check_password('test', enc_token1)
True

check_password方法做了一些事情,比如检查哈希算法是否已经改变。它返回实现verify基类的算法的BasePasswordHasher方法的结果。以下是source of the PBKDF2PasswordHasher

的实施示例
def verify(self, password, encoded):
    algorithm, iterations, salt, hash = encoded.split('$', 3)
    assert algorithm == self.algorithm
    encoded_2 = self.encode(password, salt, int(iterations))
    return constant_time_compare(encoded, encoded_2)

注意如何通过在' $'上分割encoded_string来找到salt,因为Django docs note

  

User对象的password属性是这种格式的字符串:

<algorithm>$<iterations>$<salt>$<hash>