📌  相关文章
📜  在 NodeJS 中使用 OTP 进行电子邮件验证(1)

📅  最后修改于: 2023-12-03 15:37:24.931000             🧑  作者: Mango

在 NodeJS 中使用 OTP 进行电子邮件验证

如果你的应用程序需要进行电子邮件验证,你可能会考虑使用 OTP(一次性密码)来保证安全性。本文将介绍如何在 NodeJS 中使用 OTP 进行电子邮件验证。

OTP 简介

OTP 是一种用于验证身份的方法,它基于时间或者计数器生成密码。使用 OTP,每个用户都可以拥有一个唯一的密码,这个密码只能用一次。

在 OTP 的基础上,也可以继续进行加密增强以提高安全性,例如使用 TOTP(基于时间的 OTP)或 HOTP(基于计数器的 OTP)。

在 NodeJS 中使用 TOTP 进行电子邮件验证

我们可以使用 speakeasy 包轻松地在 NodeJS 中使用 TOTP 进行电子邮件验证。以下是典型的工作流程:

  1. 用户在应用程序中输入自己的电子邮件地址,并点击“验证”按钮。
  2. 应用程序将生成一个 TOTP 密钥,并将其存储在自己的数据库中。
  3. 应用程序将 TOTP 密钥通过电子邮件发送给用户。
  4. 用户在其设备上下载 TOTP 应用程序,并输入通过电子邮件发送的 TOTP 密钥。
  5. 用户会收到一个 TOTP 代码,他们输入该代码以证明他们拥有该 TOTP 密钥并获得验证。

以下是如何在 NodeJS 中实现这个工作流程的示例代码:

const express = require('express');
const speakeasy = require('speakeasy');
const QRCode = require('qrcode');
const nodemailer = require('nodemailer');

const app = express();

// Generate TOTP secret key
app.get('/api/generate-secret', (req, res) => {
  const secret = speakeasy.generateSecret({length: 20});
  res.send(secret);
});

// Generate TOTP QR code
app.get('/api/generate-qr-code', (req, res) => {
  const otpauthUrl = speakeasy.otpauthURL({
    secret: req.query.secret.base32,
    label: 'My App',
    algorithm: 'sha1',
    encoding: 'base32'
  });
  QRCode.toDataURL(otpauthUrl)
    .then(dataUrl => {
      res.send(dataUrl);
    });
});

// Send TOTP key via email
app.post('/api/send-email', (req, res) => {
  const email = req.body.email;
  const secret = req.body.secret.base32;
  const transporter = nodemailer.createTransport({
    service: 'Gmail',
    auth: {
      user: process.env.GMAIL_ACCOUNT,
      pass: process.env.GMAIL_PASSWORD
    }
  });
  const otpauthUrl = speakeasy.otpauthURL({
    secret: secret,
    label: 'My App',
    algorithm: 'sha1',
    encoding: 'base32'
  });
  const mailOptions = {
    from: process.env.GMAIL_ACCOUNT,
    to: email,
    subject: 'Verification code for My App',
    text: `Please enter the following code to verify your email address: ${speakeasy.totp({secret: secret, encoding: 'base32'})}`,
    html: `<p>Please enter the following code to verify your email address:</p><p style="font-size: 2em;font-weight: bold;">${speakeasy.totp({secret: secret, encoding: 'base32'})}</p><br/><img src="${otpauthUrl}"/>`
  };
  transporter.sendMail(mailOptions, (error, info) => {
    if (error) {
      console.error('Error occurred:', error.message);
      res.sendStatus(400);
    } else {
      console.log('Message sent');
      res.sendStatus(200);
    }
  });
});

// Verify TOTP code
app.post('/api/verify', (req, res) => {
  const secret = req.body.secret.base32;
  const code = req.body.code;
  const verified = speakeasy.totp.verify({
    secret: secret,
    encoding: 'base32',
    token: code
  });
  if (verified) {
    res.sendStatus(200);
  } else {
    res.sendStatus(400);
  }
});

app.listen(3000, () => {
  console.log('Server started on port 3000');
});

在上述示例代码中,我们生成 TOTP 密钥、生成 TOTP QR 码、通过电子邮件发送 TOTP 密钥以及验证 TOTP 代码。请注意,实际应用程序需要更多的错误处理和安全性功能。