【发布时间】:2023-06-10 18:23:01
【问题描述】:
我正在为 Web 应用程序构建后端。当新用户访问该站点并单击注册按钮时,他们会填写一个超级简单的表单,询问他们的用户名和密码,然后他们就会提交。这会提示服务器向该电子邮件地址发送验证电子邮件。然后他们会检查他们的电子邮件,单击一个链接(用于验证他们的电子邮件),然后被路由到登录页面,以便他们可以选择登录。
为了验证他们的电子邮件,当服务器生成电子邮件时,它需要创建(并存储)一个验证令牌(可能是 UUID)并将其附加到电子邮件中的此链接,使链接看起来像:
vt=12345
是“验证令牌”(也可能是 UUID)。因此,用户单击此链接,我的GET v1/users/verify
端点查看令牌,以某种方式确认其有效,并进行一些数据库更新以“激活”用户。他们现在可以登录了。
当用户想要取消订阅接收电子邮件或忘记密码并需要恢复密码以便登录时的类似场景。
退订
用户想停止接收电子邮件但仍想使用该应用程序。他们在我们发送给他们的每周时事通讯中单击“退订”链接。该链接需要包含某种类似的“取消订阅令牌”,就像上面的验证令牌一样,生成并存储在服务器上,用于验证用户取消订阅电子邮件的请求。
找回密码
这里用户忘记了密码,需要找回密码。因此,在登录屏幕上,他们单击“忘记我的密码”链接,然后会看到一个表格,他们必须在其中填写他们的电子邮件地址。服务器向该地址发送电子邮件。他们检查了这封电子邮件,其中包含一个表格链接,他们可以在其中输入新密码。此链接需要包含一个“重置密码令牌”——就像上面的验证令牌一样——生成并存储在服务器上,用于验证用户更改密码的请求。
所以这里我们要解决三个非常相似的问题,都需要使用我所说的“一次性 (OTO) 安全令牌”。这些 OTO 令牌:
- 必须在服务器端生成并持久化(可能保存到
security_tokens
表中) - 必须是可以附加到我们将从电子邮件内部公开的链接的内容
- 必须只有一次有效:一旦他们点击它,令牌就被“使用”并且不能被重复使用
我的问题
我想出的解决方案很简单……几乎太简单了。
对于令牌,我只是生成随机 UUID(36 字符)并将它们存储到具有以下字段的 security_tokens
表中:
[security_tokens]
---
id (PK)
user_id (FK to [users] table)
token (the token itself)
status (UNCLAIMED or CLAIMED)
generated_on (DATETIME when created)
当服务器创建它们时,它们是“UNCLAIMED”。当用户单击表内的链接时,他们被“认领”。后台工作人员作业将定期运行以清理任何 CLAIMED 令牌或删除任何已“过期”的 UNCLAIMED 令牌(基于其generated_on
字段)。该应用程序还将忽略之前已声明(并且尚未清理)的任何令牌。
我认为这个解决方案可行,但我不是一个超级安全的人,我担心这种方法:
- 可能会使我的应用程序受到某种类型的攻击/利用;和
- 当其他解决方案可能同样有效时,可能会重新发明*
就像上面的第二个一样,我想知道我是否应该使用与哈希/HMAC/JWT 相关的机制而不是死的简单 UUID。也许有一些聪明的加密/安全人员找到了一种方法,使这些令牌本身以安全/不可变的方式包含 CLAIM 状态和到期日期等。
【问题讨论】:
标签: security authentication hash jwt hmac