我正在生成由一次性令牌组成的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 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)


请注意如何通过在'$'上分割encode_string来找到盐,因为Django docs note表示


  User对象的password属性是以下格式的字符串:

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

关于python - 存储的盐化 token 和 token 比较,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39858364/

10-11 08:40