简体   繁体   English

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

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

I am trying to write a token based auth in flask for my android app.我正在尝试为我的 android 应用程序在烧瓶中编写一个基于令牌的身份验证。 For that I need a unique token using which I can verify the user.为此,我需要一个唯一的令牌,我可以使用它来验证用户。

Itsdangerous library provide a JSONWebSignatureSerializer function using which I can create JWT token.它的危险库提供了一个 JSONWebSignatureSerializer 函数,我可以使用它来创建 JWT 令牌。 So my first question is, is it safe to use JWT for mobile based auth ?所以我的第一个问题是,将 JWT 用于基于移动的身份验证是否安全?

Secondly, I did a little bit research on how django rest framework generates its token.其次,我对 django rest 框架如何生成其令牌进行了一些研究。

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

Is this token unique or just a random one?这个令牌是唯一的还是只是一个随机的? Which one should I use for a mobile based auth?我应该使用哪一个进行基于移动的身份验证?

What is the based way to generate a unique token for mobile application in python ?在 python 中为移动应用程序生成唯一令牌的基本方法是什么?

You can use like as mentioned the builtin uuid module.您可以像提到的那样使用内置uuid模块。 The new secrets module released in 3.6 is also capable of creating unique tokens also. 3.6 中发布的新secrets模块也能够创建独特的令牌。

from uuid import uuid4

rand_token = uuid4()

The function below creates a unique token every time it's called.下面的函数每次被调用时都会创建一个唯一的令牌。 The os.urandom method returns 20 random bytes as a string and the binascii.hexlify method converts each of those 20 bytes into 2-digit hex representation of that byte. os.urandom方法以字符串形式返回 20 个随机字节,而binascii.hexlify方法将这 20 个字节中的每一个都转换binascii.hexlify字节的 2 位十六进制表示。 This is why the return value is twice as long.这就是为什么返回值是两倍长的原因。

If you want to use this approach and need tokens to be specific length, use half of the length you need as an argument to the os.urandom method.如果您想使用这种方法并且需要令牌具有特定长度,请使用所需长度的一半作为os.urandom方法的参数。

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

OK, this is old, but I'm chiming in anyway.好吧,这已经过时了,但我还是要插嘴。 You need to decide: Do you want unique or random?你需要决定:你想要独特的还是随机的? Choose one.选一个。

If you want unique, use UUID.如果您想要唯一,请使用 UUID。 The whole purpose of UUIDs is to make sure you generate something that's unique. UUID 的全部目的是确保您生成独特的东西。 UUID stands for Universally Unique ID. UUID 代表通用唯一 ID。

If you want something that's random, use os.urandom .如果你想要一些随机的东西,使用os.urandom Truly random results cannot be limited to uniqueness constraints!真正随机的结果不能局限于唯一性约束! That'd make them not random.那会使它们不随机。 Indeed, it'd make them UUIDs.事实上,它会使它们成为 UUID。

Now, for your question, you're asking for an auth token.现在,对于您的问题,您需要一个身份验证令牌。 That means you're using this for security purposes.这意味着您出于安全目的使用它。 UUIDs are the wrong solution and generating a secure number is the right one. UUID 是错误的解决方案,而生成安全号码是正确的解决方案。 Could you have a collision when generating a random number instead of a UUID?生成随机数而不是 UUID 时会发生冲突吗? Yes.是的。 But it's unlikely unless you've got a gazillion users.但除非你有无数用户,否则这是不可能的。 You'll want to do your math on this, but my recommendation is: Don't use UUID when you mean to use random.您会想对此进行数学计算,但我的建议是:当您打算使用随机时,不要使用 UUID。

Oy.哎呀。

Look at the uuid() library.查看 uuid() 库。 Docs are here:文档在这里:

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

and a previous discussion of the question is here:之前对该问题的讨论在这里:

How to create a GUID/UUID in Python 如何在 Python 中创建 GUID/UUID

with lots of good details.有很多很好的细节。

I wrote a little helper function for generating a unique token in django models.我写了一个小辅助函数,用于在 django 模型中生成一个唯一的标记。 You can call it from the save() method of your model.您可以从模型的save()方法调用它。 It generates a candidate token using a defined function, searches the existing rows in the database for that candidate token.它使用定义的函数生成候选标记,在数据库中的现有行中搜索该候选标记。 If it finds one, it trys again, otherwise, it returns the candidate string.如果找到,则重试,否则返回候选字符串。 Note that there is a small race condition in this, but is unlikely to occur with a token function with a sufficiently large range of outputs.请注意,这里有一个小的竞争条件,但不太可能发生在具有足够大范围输出的令牌函数中。

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

Then, you can find a unique token simply by calling然后,您只需调用即可找到唯一的令牌

token = generate_unique_token(MyModelInstance, "token_field_name")

It even supports using other methods of generating tokens.它甚至支持使用其他生成令牌的方法。 For example, if you want to use the full uuid, you can simply call it like this:例如,如果你想使用完整的 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