bounty将在2天后过期。回答此问题可获得+50的声誉奖励。user2675468正在寻找来自声誉良好来源的答案。
我有一个json,日期为:
{
password: 'mySecretPwd',
validUntil: dayjs().add(1, 'hour').toDate(),
userId: '29038492132'
}
现在我想创建一个类似魔术链接(myUrl/)的东西。当用户点击链接时,它必须打开一个网页,用户必须将密码写入一个文本字段。提交后,它发送一个包含用户输入和链接中的令牌的请求。然后服务器检查输入是否等于令牌中的用户输入,并验证用户是否有效。
现在我的问题是如何实现它。我的代码看起来像这样:
const crypto = require('crypto')
const algorithm = 'aes-256-ctr'
const secretKey = process.env.JWT_TEST_RESULT_SECRET
export const encrypt = (text) => {
const iv = crypto.randomBytes(16)
const cipher = crypto.createCipheriv(algorithm, secretKey, iv)
const encrypted = Buffer.concat([cipher.update(text), cipher.final()])
return {
iv: iv.toString('hex'),
content: encrypted.toString('hex')
}
}
因为我需要iv来解码,所以我会创建如下链接:myUrl/<content>_<iv>
这是不是一个好的和安全的方法?
我希望你能提供一些意见谢谢
1条答案
按热度按时间r3i60tvu1#
我假设您希望在项目中实现2fa。
对于2fa身份验证,您将在用户尝试登录时重置用户密码,然后向他们发送一个令牌作为响应,并将其保存在项目内存中(在变量或状态管理中)。
为了实现这种方式(不存储令牌),最好在他们要求登录后给他们发邮件,(你可以使用SendGrid)他们可以点击并插入密码的链接,当然沿着他们的新密码(我建议你考虑只使用带有静态密码的令牌或只向他们发送密码)。
尊敬用户,您的新密码是:NEW_PASSWORD,请在下面的链接中输入您的密码:您的前端.com/插入密码/?令牌=新令牌&用户名=用户名(我建议您将令牌的到期时间设置为2分钟)
在前端,我们在nuxt.js中的查询中查找令牌和用户名,例如,您可以通过编写以下内容访问查询中的项目:.$route.query.YOUR_DESIRED_ITEM_IN_QUERY。
如果我们在查询中得到了我们想要的项目,我们要求用户插入他们的密码,否则我们将他们重定向到登录页面。
在他们插入密码后,我们将用户名、密码和令牌发送到后端进行验证。
用于验证密码并对其进行散列:
我会考虑使用bycrypt。因为它很容易使用,你想过期你的密码每1小时(我建议2分钟)。没有必要更复杂的东西。
但是如果您希望为用户提供一个静态密码(并且您希望它尽可能安全),并且除非用户自己更新它,否则不会随时间而更改,那么我建议您不要在数据库中存储密码(即使是它的散列版本)。
为了达到这个目的,你必须用你的密码作为密钥来散列来自用户的不可改变的数据(如ID),并将散列数据存储在数据库中,这样,即使你存储的散列数据被解密,攻击者也不会访问密码,相反,他们会获得ID。
第一步:将您的密码转换为32进制。(您将使用您的密码作为您的密钥稍后),
步骤2:加密
在这一步中,你将用户ID作为“textToEncrypt”传递,并将转换后的密码作为“secretKey”传递。
最后一步:解密
型
encryptedText是你已经存储到你的数据库中的文本,secretKey是用户已经插入的密码,并且你已经运行了你的转换密码函数,id是你已经用于加密的用户id.如果密码有效,这个函数返回true,如果密码无效,返回false.
PS:如果你的项目不需要那么多的安全性,我仍然建议你使用bycrypt