如何生成唯一令牌(用于电子邮件验证)?

时间:2016-01-22 12:41:32

标签: random go

我想实现一个系统,在用户注册后,用户将收到一封电子邮件,其中包含一个链接,用于验证此电子邮件是否适用于该用户。

我生成用于验证电子邮件的令牌的方式如下:

import (
    "crypto/rand"
    "encoding/base64"
)

func generateToken() (string, error) {
    b := make([]byte, 35)
    _, err := rand.Read(b)
    if err != nil {
        return "", err
    }
    return base64.URLEncoding.EncodeToString(b), nil
}

但我想问的是这种方法是否合适?如何使这个方法生成的所有令牌都是唯一的?

实施此系统的正常方法是什么?

请给我一些想法,并告诉我这种生成令牌的方法是否合适。

感谢。

3 个答案:

答案 0 :(得分:2)

查看https://godoc.org/code.google.com/p/go-uuid/uuid#NewRandom

并且您可能想要考虑将其存储在具有电子邮件地址的数据库中,并且可能存在到期日期/时间,以便验证不会永久保留在那里。您可能只想让人们在24小时或7天内验证等等。有另一份工作定期清理过期和未经验证的电子邮件。

答案 1 :(得分:0)

两点:

  • 不,所提出的方法不能保证它们是唯一的。
  • 您无需将所有您的令牌设为唯一。

扩展这些要点......

您正在处理一组未完成的验证请求。 那就是:

  1. 用户提出请求;
  2. 您生成一个唯一的验证令牌,存储到某个预先存储的数据库中。无论如何,这都需要验证才能正常工作。
  3. 用户会收到您的电子邮件,并点击其中包含您的令牌的链接。此时,您将从持久存储中删除有关此待处理验证请求的信息。
  4. 正如您所看到的,在任何时候您只有几个未完成的验证请求。因此,这种情况有两个重要特性:

    • 您只需要这些未完成请求的令牌彼此不同。可以使验证令牌与过去(或将来)的某个请求相同。
    • 你的代币必须难以猜测(显然)。我相信你已经明白了。

    因此,生成新令牌的方法如下:

    1. 生成难以猜测的内容。

    2. 将其与绑定到存储空间中待处理的待处理/待处理验证请求的令牌进行比较。

      如果您发现具有相同令牌的未完成请求,则会发生冲突,请转到步骤(1)并重复。

      否则令牌就可以了,所以继续使用它并保留有关此请求的数据。

    3. 请求通过验证后,将其从存储中删除。

    4. 用于生成令牌的精确算法并不重要。我会说一个UUID或类似SHA-256/512的东西可以通过一些随机数据计算出来。

答案 2 :(得分:-1)

无需独一无二。您可以寻找更安全/更复杂的解决方案,但只需将随机数放在十六进制中即可

strconv.FormatInt(rand.Int63(), 16)

https://play.golang.org/p/l9U2uUZNAV