我正在生成由一次性令牌组成的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
但是,这无助于我从数据库中检索与令牌相对应的条目,并且我无法对其进行验证。
最佳答案
使用简单的字符串相等性检查两个散列标记和盐渍标记将不起作用。 Django docs for password management在django.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)
请注意如何通过在'$'上分割encode_string来找到盐,因为Django docs note表示
User对象的password属性是以下格式的字符串:
<algorithm>$<iterations>$<salt>$<hash>
关于python - 存储的盐化 token 和 token 比较,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39858364/