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

AWS Cognito forgot_password Python调用不存在用户未抛异常问题

AWS Cognito forgot_password接口不返回用户不存在异常问题解答

问题原因

  • 该现象是AWS Cognito的用户存在性枚举防护机制导致的,这是Cognito默认开启的安全特性,目的是防止攻击者通过批量调用接口遍历判断哪些用户名/手机号在用户池中真实存在,避免账号泄露风险。
  • 开启该特性后,不管传入的用户名是否真实存在,forgot_password、sign_in等公开接口都会统一返回200成功响应,不会抛出UserNotFoundException异常。

掩码邮箱说明

你看到的n***@y***.com这类掩码邮箱是Cognito基于输入的用户名生成的响应内容:

  • 对于真实存在的用户,返回的是用户真实绑定邮箱/手机号的掩码
  • 对于不存在的用户,Cognito会基于输入的用户名做哈希运算生成对应的虚假掩码,因此不同的不存在用户名会返回不同的虚假掩码,完全模拟真实用户的响应逻辑,攻击者无法通过返回内容区分用户是否真实存在。

修复方案

你可以根据业务安全需求选择以下两种方案:

方案1:关闭用户存在性枚举防护(存在安全风险)

如果业务不需要防护用户枚举攻击,可以手动关闭该特性:

  1. 打开AWS Cognito控制台,进入对应的用户池
  2. 切换到「应用集成」标签页,找到你使用的应用客户端
  3. 关闭「防止用户存在性错误」(Prevent user existence errors)选项即可
    关闭后你的现有代码不需要修改,不存在的用户调用接口时会正常抛出UserNotFoundException,你的异常捕获逻辑可以正常触发。

方案2:增加用户存在性校验逻辑(推荐,保留安全特性)

如果要保留Cognito的安全防护能力,可以在调用forgot_password前先通过管理员接口校验用户是否存在,需要先给Lambda执行角色添加cognito-idp:AdminGetUser的权限,修改后的代码如下:

import json
import boto3
import botocore.exceptions
import hmac
import hashlib
import base64
import uuid
USER_POOL_ID = 'us-east-X_XXX'
CLIENT_ID = 'XXXXXXXXXX'
CLIENT_SECRET = 'XXXXXXXXXXXXX'


def get_secret_hash(username):
    msg = username + CLIENT_ID
    dig = hmac.new(str(CLIENT_SECRET).encode('utf-8'),
                   msg=str(msg).encode('utf-8'),
                   digestmod=hashlib.sha256).digest()
    d2 = base64.b64encode(dig).decode()
    return d2


def lambda_handler(event, context):
    for field in ["username"]:
        if not event.get(field):
            return {"error": False, "success": True, 'message': f"{field} is not present", "data": None}
    client = boto3.client('cognito-idp')
    username = event['username']
    
    # 新增:先校验用户是否存在
    try:
        client.admin_get_user(
            UserPoolId=USER_POOL_ID,
            Username=username
        )
    except client.exceptions.UserNotFoundException:
        return {"error": True, "success": False, "message": "Username doesnt exists"}
    except Exception as e:
        return {"error": True, "success": False, "message": f"Check user exist error {e.__str__()} "}
    
    try:
        print('username - ', username)
        response = client.forgot_password(
            ClientId=CLIENT_ID,
            SecretHash=get_secret_hash(username),
            Username=username,
        )
    except client.exceptions.InvalidParameterException:
        return {"error": True, "success": False, "data": None, "message": f"User <{username}> is not confirmed yet"}
    except Exception as e:
        return {"error": True, "success": False, "message": f"Unknown error {e.__str__()} "}

    print(response)
    return {"error": False, "success": True, "message": f"Please check your Registered email id for validation code", "data": None}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 16:15:06