You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS应用基于AWS User Pool实现仅手机号登录:已确认用户OTP发送方法

嘿,刚好做过类似的AWS Cognito登录流程,给你详细说下怎么给已确认状态的用户发送登录用的OTP,分两种实用方案,你可以根据自己的场景选择:

方案1:自定义认证流程(推荐纯OTP登录场景)

这是最灵活的方式,适合完全基于手机号+OTP的无密码登录,核心是借助Cognito的自定义认证触发器和API完成流程:

步骤拆解

  1. 配置Cognito User Pool触发器
    • 进入你的User Pool控制台,找到「触发器」选项卡,设置「自定义认证(Custom Auth)」对应的Lambda函数,这个函数负责生成OTP、发送短信以及验证OTP。
  2. 前端发起登录请求
    调用InitiateAuth API,告诉Cognito要启动自定义认证流程:
    import { CognitoIdentityProviderClient, InitiateAuthCommand } from "@aws-sdk/client-cognito-identity-provider";
    
    const client = new CognitoIdentityProviderClient({ region: "你的AWS区域" });
    
    const initiateAuthParams = {
      AuthFlow: "CUSTOM_AUTH",
      ClientId: "你的App Client ID",
      AuthParameters: {
        USERNAME: "用户输入的手机号" // 假设你的用户名是手机号
      }
    };
    
    const command = new InitiateAuthCommand(initiateAuthParams);
    const response = await client.send(command);
    // 此时会收到 ChallengeName: "CUSTOM_CHALLENGE" 和 Session 会话值
    
  3. Lambda生成并发送OTP
    自定义认证Lambda会被触发,生成随机OTP并通过短信发送给用户,同时临时存储OTP用于后续验证:
    const AWS = require('aws-sdk');
    const sns = new AWS.SNS({ region: '你的AWS区域' });
    const crypto = require('crypto');
    
    exports.handler = async (event) => {
      if (event.request.challengeName === 'CUSTOM_CHALLENGE') {
        // 第一次触发:生成并发送OTP
        if (!event.request.session || event.request.session.length === 0) {
          const otp = crypto.randomInt(100000, 999999).toString();
          // 把OTP存到Cognito的私有挑战参数中,后续验证用
          event.response.privateChallengeParameters = { otp };
          // 用SNS发送验证码短信
          await sns.publish({
            Message: `你的登录验证码是:${otp}(5分钟内有效)`,
            PhoneNumber: event.userName // 用户名即手机号
          }).promise();
          event.response.challengeMetadata = 'CUSTOM_OTP_CHALLENGE';
        } else {
          // 第二次触发:验证用户提交的OTP
          const expectedOtp = event.request.privateChallengeParameters.otp;
          const submittedOtp = event.request.challengeAnswer;
          if (submittedOtp === expectedOtp) {
            event.response.issueTokens = true; // 验证通过,颁发令牌
            event.response.failAuthentication = false;
          } else {
            event.response.issueTokens = false;
            event.response.failAuthentication = true;
          }
        }
      }
      return event;
    };
    
  4. 前端提交OTP完成登录
    用户收到验证码后,调用RespondToAuthChallenge API提交OTP,完成认证:
    import { RespondToAuthChallengeCommand } from "@aws-sdk/client-cognito-identity-provider";
    
    const respondParams = {
      ChallengeName: "CUSTOM_CHALLENGE",
      ClientId: "你的App Client ID",
      Session: response.Session, // 上一步InitiateAuth返回的会话值
      ChallengeResponses: {
        USERNAME: "用户输入的手机号",
        ANSWER: "用户输入的6位OTP"
      }
    };
    
    const respondCommand = new RespondToAuthChallengeCommand(respondParams);
    const authResult = await client.send(respondCommand);
    // authResult中包含IdToken、AccessToken、RefreshToken,完成登录
    
方案2:借助SMS MFA(适合已有密码+二次验证场景)

如果你的用户池已经启用了SMS多因素认证,且用户已绑定手机号作为MFA方式,可以用这个流程:

  • 前端调用InitiateAuth(AuthFlow设为USER_PASSWORD_AUTH或USER_SRP_AUTH),传入用户名和密码;
  • Cognito会触发MFA挑战,自动发送OTP到用户手机号;
  • 用户输入OTP后,调用RespondToAuthChallenge完成登录。

不过这个方案需要用户设置密码,如果你是纯无密码的OTP登录,方案1更适配你的需求。

关键注意事项
  • 确保你的App Client已启用对应的认证流程(比如「自定义认证」),在App Client的「认证流程」选项中勾选对应选项;
  • 发送短信的Lambda需要配置SNS的Publish权限;
  • OTP建议设置过期时间(比如5分钟),避免重复使用,你可以在Lambda中加入时间戳逻辑来校验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:28:44