无数据库OTP——一个概念

OTP 系统如何工作(据我所知)

第一种方式

首先,用户进入身份验证页面,然后他会看到一个表单,他必须输入电子邮件或电话号码,并请求一个 OTP 来验证该电子邮件/电话,然后他会收到一个 OTP。然后他复制该 OTP 并将其粘贴到框中,现在该电子邮件/电话已验证。

第二种方式

这样,他就会在邮件中收到一个链接,当他点击该链接时,电子邮件就会得到验证。

后端发生了什么

当用户通过向后端发送邮件请求 otp 时,后端会创建一个随机字符串,并将其与电子邮件一起存储在 redis 缓存中,并指定有效期。当用户发送该 otp 时,后端会将该 otp 与存储的 otp 进行匹配。

概念

想法

每次我创建这个身份验证系统时,我都会想我是否真的需要一个数据库,而 Redish 实例一个月的费用为 1500 印度卢比,我认为对于一个玩具项目来说,这太贵了,因为我们真的不想将 OTP 用于任何其他目的。所以我想使用哈希之类的东西来完全消除数据库。

方法

让我们将 OTP 分为两部分

  • 原始 OTP 字符串
  • 散列 OTP 字符串 原始 OTP 字符串将发送到电子邮件/电话 散列 OTP 将与请求的用户(浏览器)共享
  • 在下一个请求中,用户将提供电子邮件中的 OTP 和存储的哈希 OTP。在后端,我们可以比较它们并判断是否匹配。

    但用户可以更改哈希并发送它。因此,这里有 JSON Web 令牌,我们可以将哈希和电子邮件添加到 JWT,以便用户无法更改哈希,我们还可以为 OTP 添加 JWT 到期时间。

    通常,OTP 是 6 位数字。因此,一个人可以创建一个包含所有 6 位哈希值的彩虹表,并对其进行匹配,从而知道 OTP。为了解决这个问题,我们可以使用 hmac,它需要一个起始密钥,因此暴力破解是不可能的。

    export function hashedOTP(otp: string) {
      return crypto.createHmac('sha256', process.env.CRYPTO_SECRET).update(otp).digest('hex');
    }

    演示

    工作演示 - https://db-less-otp.netlify.app/

    后端 Github Repo - https://github.com/SBRakeshRath/DB-less-OTP-Backend

    前端 Github Repo - https://github.com/SBRakeshRath/DB-less-OTP-Frontend

    ** 我使用的是 Gmail 账户,所以我不希望你发送垃圾邮件,因为你只能发送 500 封电子邮件

    请指出漏洞及其修复方法。