简体   繁体   English

Python Google App Engine中的密码重置令牌

[英]Password reset token in Python Google App Engine

I want to generate a password reset token for a User model that I have with Google App Engine. 我想为我使用Google App Engine的用户模型生成密码重置令牌。 Apparently we're not allowed to use Django that easily with GAE, so the raw code for the Django method for generating tokens is: 显然,我们不允许在GAE中轻松使用Django,因此用于生成令牌的Django方法的原始代码为:

def _make_token_with_timestamp(self, user, timestamp):
    # timestamp is number of days since 2001-1-1.  Converted to
    # base 36, this gives us a 3 digit string until about 2121
    ts_b36 = int_to_base36(timestamp)

    # By hashing on the internal state of the user and using state
    # that is sure to change (the password salt will change as soon as
    # the password is set, at least for current Django auth, and
    # last_login will also change), we produce a hash that will be
    # invalid as soon as it is used.
    # We limit the hash to 20 chars to keep URL short
    key_salt = "django.contrib.auth.tokens.PasswordResetTokenGenerator"

    # Ensure results are consistent across DB backends
    login_timestamp = user.last_login.replace(microsecond=0, tzinfo=None)

    value = (unicode(user.id) + user.password +
            unicode(login_timestamp) + unicode(timestamp))
    hash = salted_hmac(key_salt, value).hexdigest()[::2]
    return "%s-%s" % (ts_b36, hash)

Python is not my language of expertise, so I'll need some help writing a custom method similar to the one above. Python不是我的专业语言,因此在编写类似于上述方法的自定义方法时,我需要一些帮助。 I just have a couple questions. 我只是有几个问题。 First, what is the purpose of the timestamp? 首先,时间戳的目的是什么? And Django has its own User system, while I'm using a simple custom User model of my own. Django有自己的用户系统,而我使用的是自己的简单自定义用户模型。 What aspects from the above code will I need to retain, and which ones can I do away with? 我需要保留上述代码中的哪些方面,我可以删除哪些方面?

well, the check_token -method looks like this: 好吧, check_token方法看起来像这样:

def check_token(self, user, token):
    """
    Check that a password reset token is correct for a given user.
    """
    # Parse the token
    try:
        ts_b36, hash = token.split("-")
    except ValueError:
        return False

    try:
        ts = base36_to_int(ts_b36)
    except ValueError:
        return False

    # Check that the timestamp/uid has not been tampered with
    if not constant_time_compare(self._make_token_with_timestamp(user, ts), token):
        return False

    # Check the timestamp is within limit
    if (self._num_days(self._today()) - ts) > settings.PASSWORD_RESET_TIMEOUT_DAYS:
        return False

    return True
  • first the timestamp part of the token is converted back to integer 首先将令牌的时间戳部分转换回整数
  • then a new token is generated using that timestamp and compared to the old token. 然后使用该时间戳生成新令牌并将其与旧令牌进行比较。
    Note that when generating a token the timestamp of the last login is one of the parameters used to calculate the hash. 请注意,在生成令牌时,上次登录的时间戳是用于计算哈希的参数之一。 That means that after a user login the old token would become invalid, which makes sense for a password reset token. 这意味着在用户登录后,旧令牌将变得无效,这对于密码重置令牌是有意义的。
  • lastly a check is performed to see if the token hasn't alerady timed out. 最后,执行检查以查看令牌是否还没有超时。

it's a fairly simple process, and also fairly secure. 这是一个相当简单的过程,而且也相当安全。 If you wanted to use the reset-system to break into an account, you'd have to know the user's password and last login timestamp to calculate the hash. 如果要使用重置系统来破解帐户,则必须知道用户的密码和上次登录时间戳才能计算哈希值。 And if you knew that wouldn't need to break into the account... 如果您知道那不需要打入帐户...

So if you want to make a system like that, it's important when generating the hast to use parameters that are not easy to guess, and of course to use a good, salted hash function. 因此,如果要创建这样的系统,则在生成hast时使用不容易猜到的参数,当然也要使用良好的盐化哈希函数非常重要。 Django uses sha1 , using other hashlib digests would of course be easily possible. Django 使用sha1 ,当然可以很容易地使用其他hashlib摘要。

Another way would be to generate a random password reset token and store it in the database, but this potentially wastes a lot of space as the token-column would probably be empty for most of the users. 另一种方法是生成一个随机的密码重置令牌并将其存储在数据库中,但这可能会浪费大量空间,因为对于大多数用户而言,令牌列可能是空的。

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

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