繁体   English   中英

如何在python中生成唯一的身份验证令牌?

[英]How to generate a unique auth token in python?

我正在尝试为我的 android 应用程序在烧瓶中编写一个基于令牌的身份验证。 为此,我需要一个唯一的令牌,我可以使用它来验证用户。

它的危险库提供了一个 JSONWebSignatureSerializer 函数,我可以使用它来创建 JWT 令牌。 所以我的第一个问题是,将 JWT 用于基于移动的身份验证是否安全?

其次,我对 django rest 框架如何生成其令牌进行了一些研究。

def generate_key(self):
    return binascii.hexlify(os.urandom(20)).decode()  

这个令牌是唯一的还是只是一个随机的? 我应该使用哪一个进行基于移动的身份验证?

在 python 中为移动应用程序生成唯一令牌的基本方法是什么?

您可以像提到的那样使用内置uuid模块。 3.6 中发布的新secrets模块也能够创建独特的令牌。

from uuid import uuid4

rand_token = uuid4()

下面的函数每次被调用时都会创建一个唯一的令牌。 os.urandom方法以字符串形式返回 20 个随机字节,而binascii.hexlify方法将这 20 个字节中的每一个都转换binascii.hexlify字节的 2 位十六进制表示。 这就是为什么返回值是两倍长的原因。

如果您想使用这种方法并且需要令牌具有特定长度,请使用所需长度的一半作为os.urandom方法的参数。

def generate_key(self):
    return binascii.hexlify(os.urandom(20)).decode()

好吧,这已经过时了,但我还是要插嘴。 你需要决定:你想要独特的还是随机的? 选一个。

如果您想要唯一,请使用 UUID。 UUID 的全部目的是确保您生成独特的东西。 UUID 代表通用唯一 ID。

如果你想要一些随机的东西,使用os.urandom 真正随机的结果不能局限于唯一性约束! 那会使它们不随机。 事实上,它会使它们成为 UUID。

现在,对于您的问题,您需要一个身份验证令牌。 这意味着您出于安全目的使用它。 UUID 是错误的解决方案,而生成安全号码是正确的解决方案。 生成随机数而不是 UUID 时会发生冲突吗? 是的。 但除非你有无数用户,否则这是不可能的。 您会想对此进行数学计算,但我的建议是:当您打算使用随机时,不要使用 UUID。

哎呀。

查看 uuid() 库。 文档在这里:

https://docs.python.org/2/library/uuid.html

之前对该问题的讨论在这里:

如何在 Python 中创建 GUID/UUID

有很多很好的细节。

我写了一个小辅助函数,用于在 django 模型中生成一个唯一的标记。 您可以从模型的save()方法调用它。 它使用定义的函数生成候选标记,在数据库中的现有行中搜索该候选标记。 如果找到,则重试,否则返回候选字符串。 请注意,这里有一个小的竞争条件,但不太可能发生在具有足够大范围输出的令牌函数中。

def generate_unique_token(Model,
                      token_field="token",
                      token_function=lambda: uuid.uuid4().hex[:8]):
"""
Generates random tokens until a unique one is found
:param Model: a Model class that should be searched
:param token_field: a string with the name of the token field to search in the model_class
:param token_function: a callable that returns a candidate value
:return: the unique candidate token
"""
unique_token_found = False
while not unique_token_found:
    token = token_function()
    # This weird looking construction is a way to pass a value to a field with a dynamic name
    if Model.objects.filter(**{token_field:token}).count() is 0:
        unique_token_found = True
return token

然后,您只需调用即可找到唯一的令牌

token = generate_unique_token(MyModelInstance, "token_field_name")

它甚至支持使用其他生成令牌的方法。 例如,如果你想使用完整的 uuid,你可以简单地像这样调用它:

token = generate_unique_token(MyModel, "token_field_name", lambda: uuid.uuid4().hex)

一个可能的解决方案是 AES 加密令牌过期的时间 ​​+ 用户名,这使得发现过期令牌变得相当容易,并且不需要额外的令牌数据库空间

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM