簡體   English   中英

在python中生成重置令牌的最佳方法是什么?

[英]what is the best way to generate a reset token in python?

我正在嘗試為密碼重置進行驗證過程,我使用的是兩個值:紀元時間,我想使用用戶的舊密碼 (pbkdf2) 作為密鑰,

因為我不想得到非 ASCII 字符,所以我使用了SimpleEncode 庫,因為它很快,因為它只是一個使用密鑰的 BASE64,但問題是密碼太長(196 個字符)所以我得到了一個長密鑰!

我所做的是拆分結果code = simpleencode.encode(key,asci)[::30] ,但這不會是唯一的!

為了了解它是如何工作的,我嘗試了 Facebook 重置過程,但給出的是一個數字! 那么這個過程是如何工作的,他們不是使用密鑰來使某人難以偽造鏈接來重置某人的密碼嗎?

更新:算法將如何工作:

1- 使用 epoch time.time()獲取時間

2-生成紀元時間的Base64(用於URL)和紀元時間值+一個密鑰,這個密鑰是PBKDF2(密碼)。

3- 生成網址 www.example.com/reset/user/Base64(time.time()) 並發送此網址 + simpleencode.encode(key,asci)[::30]

4-當用戶點擊URL時,他把生成的代碼,這個生成的代碼,如果與URL匹配,則讓他修改密碼,否則,它是一個忘記URL!

不確定這是最好的方法,但我可能只是生成一個 UUID4,可以在 URL 中使用它來重置密碼並在“n”個時間后過期。

>>> import uuid
>>> uuid.uuid4().hex
'8c05904f0051419283d1024fc5ce1a59'

您可以使用諸如http://redis.io 之類的東西來保存該密鑰,並使用相應用戶 ID 的值並設置其生存時間。 因此,當某些內容來自http://example.com/password-reset/8c05904f0051419283d1024fc5ce1a59 時,它會查看它是否有效,如果有效,則允許更改以設置新密碼。

如果您確實想要一個“驗證引腳”,那么與令牌一起存儲一個小的隨機密鑰,例如:

>>> from string import digits
>>> from random import choice
>>> ''.join(choice(digits) for i in xrange(4))
'2545'

並要求在重置鏈接上輸入。

到目前為止,最簡單的方法是使用ItsDangerous庫:

您可以序列化用戶 ID 並對其進行簽名,以將時事通訊取消訂閱到 URL 中。 這樣您就不需要生成一次性令牌並將它們存儲在數據庫中。 任何類型的帳戶激活鏈接和類似的東西都是一樣的。

您還可以嵌入時間戳,因此無需涉及數據庫或隊列即可輕松設置時間段。 它都是經過加密簽名的,因此您可以輕松查看它是否被篡改。

>>> from itsdangerous import TimestampSigner
>>> s = TimestampSigner('secret-key')
>>> string = s.sign('foo')
>>> s.unsign(string, max_age=5)
Traceback (most recent call last):
  ...
itsdangerous.SignatureExpired: Signature age 15 > 5 seconds

為什么不為此目的僅使用 jwt 作為令牌,也可以為其設置過期時間,因此也可以為令牌設置過期日期。

  1. 生成用密鑰加密的令牌(JWT)
  2. 發送包含以令牌為查詢參數的鏈接的郵件(當用戶打開鏈接時,頁面可以讀取令牌)
  3. 在保存新密碼之前驗證令牌

為了生成 jwt 令牌,我使用pyjwt 下面的代碼片段顯示了如何在 24 小時(1 天)的到期時間完成並使用密鑰簽名:

import jwt
from datetime import datetime, timedelta, timezone

secret = "jwt_secret"
payload = {"exp": datetime.now(timezone.utc) + timedelta(days=1), "id": user_id}
token = jwt.encode(payload, secret, algorithm="HS256")
reset_token = token.decode("utf-8")

下面的代碼片段顯示了如何在 Django 中設置令牌驗證和新密碼。 如果令牌已過期或已被篡改,則會引發異常。

secret = "jwt_secret"
claims = jwt.decode(token, secret, options={"require_exp": True})
# Check if the user exists
user = User.objects.get(id=claims.get("id"))
user.set_password(password)
user.save()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM