AWS Amplify:自定义UI场景下忘记密码功能实现问题咨询
首先得澄清一个误解:Cognito并不会默认哈希存储邮箱地址——你看到的“唯一哈希值”大概率是用户的sub(Cognito分配的唯一用户标识符),而不是邮箱或者用户名。如果管理员是在AWS控制台注册用户时,把邮箱设置为用户名,那用户名就是明文的邮箱地址;如果用户名是其他值,邮箱只是用户属性,那这个属性也是可以被检索到的。
接下来分两种场景给你具体的实现方案:
场景1:用户名就是邮箱地址
这是最直接的情况,你完全不需要额外获取用户名,因为用户输入的邮箱本身就是Cognito的用户名。直接用Amplify的Auth.forgotPassword()方法即可触发密码重置流程:
async function handlePasswordResetRequest(email) { try { // 直接传入用户输入的邮箱(即用户名) await Auth.forgotPassword(email); // 执行到这里,Cognito已经向该邮箱发送了验证码 alert("密码重置验证码已发送至你的邮箱,请查收"); } catch (error) { console.error("重置请求失败:", error); if (error.code === 'UserNotFoundException') { alert("该邮箱对应的账号不存在"); } else { alert("请求失败,请稍后重试"); } } }
调用这个方法后,Cognito会自动验证该用户名(邮箱)是否存在,存在的话就发送验证码到用户邮箱,之后你可以引导用户输入验证码和新密码,调用Auth.forgotPasswordSubmit()完成重置。
场景2:用户名≠邮箱,邮箱是用户属性
这种情况下,普通前端用户没有权限直接搜索Cognito用户列表,所以需要借助后端服务(比如AWS Lambda)来完成“通过邮箱找用户名”的操作,再触发密码重置:
步骤1:创建Lambda函数(后端处理逻辑)
这个Lambda需要有Cognito的ListUsers和AdminForgotPassword权限,代码示例(Node.js):
const AWS = require('aws-sdk'); const cognitoISP = new AWS.CognitoIdentityServiceProvider(); exports.handler = async (event) => { const { email } = JSON.parse(event.body); const USER_POOL_ID = "你的Cognito用户池ID"; try { // 搜索邮箱匹配的用户 const searchParams = { UserPoolId: USER_POOL_ID, Filter: `email = "${email}"`, Limit: 1 // 只取第一个匹配的用户(避免重复邮箱) }; const searchResult = await cognitoISP.listUsers(searchParams).promise(); if (searchResult.Users.length === 0) { return { statusCode: 404, body: JSON.stringify({ message: "该邮箱对应的账号不存在" }) }; } const targetUsername = searchResult.Users[0].Username; // 触发管理员发起的密码重置 await cognitoISP.adminForgotPassword({ UserPoolId: USER_POOL_ID, Username: targetUsername }).promise(); return { statusCode: 200, body: JSON.stringify({ message: "密码重置验证码已发送至你的邮箱" }) }; } catch (err) { console.error("处理请求出错:", err); return { statusCode: 500, body: JSON.stringify({ message: "服务器内部错误" }) }; } };
步骤2:前端调用Lambda(通过API Gateway)
把上面的Lambda配置到API Gateway后,前端可以通过HTTP请求调用:
async function handlePasswordResetRequest(email) { try { const response = await fetch("你的API Gateway端点URL", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ email }) }); const result = await response.json(); alert(result.message); } catch (err) { console.error("请求失败:", err); alert("请求出错,请稍后重试"); } }
补充说明
你之前查看的Amplify Auth代码之所以假设已有用户名,是因为forgotPassword方法本身就是设计为接收用户名参数的——如果你的用户名就是邮箱,那直接用邮箱作为参数就完全符合这个设计,不需要额外处理。
内容的提问来源于stack exchange,提问作者Fesch

