You need to enable JavaScript to run this app. 如何返回函数执行结果?实现Node.js两步验证码的前端页面输入
优惠活动
大模型
产品
解决方案
定价
更多

如何返回函数执行结果?实现Node.js两步验证码的前端页面输入

两步登录流程改造实现方案

你现有代码存在两个会导致流程跑不通的硬伤:

  • 路由处理函数完全没有调用响应对象返回内容,前端发起的登录请求会一直挂起直到超时
  • 登录SDK的2FA输入逻辑默认绑定了服务端命令行的stdin读取,没有做拦截,导致验证码输入只能在cmd完成

核心改造思路

因为整个登录流程是「提交账号密码→校验通过触发2FA要求→提交验证码→最终登录完成」的跨异步阶段流程,不需要在单个HTTP请求里等待全流程走完,只需要把每个阶段的状态通过接口返回给前端,拆分两次请求对接不同阶段的逻辑即可。

具体代码实现

1. 拦截SDK的默认命令行输码逻辑

首先在服务端维护几个临时变量,用来暂存当前登录流程的上下文,替代原来的cmd输入逻辑:

// 暂存当前待处理的2FA回调、当前登录流程的响应对象
let currentPending2FACallback = null
let currentPasswordSubmitRes = null
let currentLoginResultRes = null

// 监听SDK触发的需要2FA验证码的事件
client.on('authCodeRequired', (codeSubmitCallback) => {
  // 把SDK的验证码提交回调暂存,替代之前的stdin手动输入
  currentPending2FACallback = codeSubmitCallback
  // 如果当前还有等待的账号密码提交请求,直接返回需要2FA的状态
  if (currentPasswordSubmitRes) {
    currentPasswordSubmitRes.json({
      code: 1001,
      need2FA: true,
      msg: '请输入手机收到的5位两步验证码'
    })
    currentPasswordSubmitRes = null
  }
})

2. 改造原账号密码提交接口

app.post('/api/login/password', (request, response) => {
  // 暂存当前接口的响应对象,等2FA事件触发时可以直接返回状态
  currentPasswordSubmitRes = response
  // 清空上一次的临时流程上下文
  currentPending2FACallback = null

  client.logOn({
    accountName: request.body.uName,
    password: request.body.uPassword,
  })

  // 加15秒超时兜底,避免请求挂起
  setTimeout(() => {
    if (currentPasswordSubmitRes) {
      currentPasswordSubmitRes.json({code: 500, msg: '登录请求超时,请重试'})
      currentPasswordSubmitRes = null
    }
  }, 15000)
})

3. 新增2FA验证码提交接口

专门接收前端传入的验证码,传给之前暂存的SDK回调,完成校验:

app.post('/api/login/2fa', (request, response) => {
  // 把当前响应对象暂存,等最终登录结果事件触发时返回
  currentLoginResultRes = response
  if (!currentPending2FACallback) {
    return response.json({code: 400, msg: '无待校验的2FA流程,请重新提交账号密码'})
  }
  const twoFactorCode = request.body.twoFactorCode
  // 把前端传的验证码提交给SDK,完全替代cmd手动输入的逻辑
  currentPending2FACallback(twoFactorCode)
})

4. 补全全流程结果的事件监听

把最终的登录成功/失败状态通过接口返回给前端:

// 登录成功事件
client.on('loggedOn', () => {
  console.log("Logged in");
  // 登录成功后下发会话凭证给前端
  if (currentLoginResultRes) {
    currentLoginResultRes.json({
      code: 200,
      msg: '登录成功',
      // 这里可以下发JWT、Cookie等登录态凭证
      token: '你的登录凭证内容'
    })
    currentLoginResultRes = null
  }
  // 清空临时上下文
  currentPending2FACallback = null
})

// 登录失败事件(包含密码错误、2FA错误等所有异常)
client.on('error', (err) => {
  console.log('登录失败', err)
  if (currentLoginResultRes) {
    currentLoginResultRes.json({
      code: 500,
      msg: err.message || '登录失败,请检查输入'
    })
    currentLoginResultRes = null
  }
  currentPending2FACallback = null
})

前端交互配合

  • 用户第一次提交账号密码时,如果接口返回need2FA: true,直接在当前页面弹出2FA输入框,提示用户输入手机收到的验证码
  • 用户输入验证码后,前端把码提交到/api/login/2fa接口,等待接口返回最终的登录成功/失败结果

线上场景注意事项

  • 上述代码是单用户测试场景的简化实现,如果是多用户并发的线上环境,不要用全局变量暂存流程上下文,需要用临时会话ID、用户提交的账号作为key,把每个登录流程的回调、响应对象做键值对存储隔离,避免不同用户的登录流程串数据
  • 部分SDK可以在初始化或者调用logOn时直接传配置禁用stdin输码逻辑,记得加上这个配置,避免服务端还是弹出cmd的输入提示
  • 所有接口都要加超时兜底,避免因为SDK事件触发不及时导致HTTP连接一直占用

内容的提问来源于stack exchange,提问作者Cone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.14 05:54:03