如何阻止同一用户触发多个AWS Lambda Authorizer?缓存机制失效问题
问题根源
API Gateway在处理并发请求时,不会等待第一个Authorizer的缓存结果生成,就会直接触发新的Authorizer调用——这就是为什么你自己实现的内部缓存没起作用,多个请求同时进来时,都没等到缓存写入就各自执行了权限校验逻辑。
实用解决方案
1. 启用API Gateway内置的Authorizer缓存(优先推荐)
这是最简单的方案,无需修改代码:
- 登录API Gateway控制台,找到对应自定义Authorizer,开启缓存开关
- 设置合适的缓存TTL:比如5分钟到1小时,根据你的权限变更频率调整,变更不频繁就设长一些
- 确认缓存密钥:如果是Token类型的Authorizer,默认用
token作为密钥,确保同一用户的请求会生成相同密钥,这样并发请求会直接命中API Gateway层面的缓存,不会重复调用Lambda
2. 在Lambda Authorizer内实现分布式锁
如果无法依赖API Gateway内置缓存(比如需要自定义缓存逻辑),可以给Authorizer添加分布式锁:
- 用DynamoDB的条件表达式实现锁:第一个请求进来时写入一条带过期时间的锁记录,后续请求检测到锁存在就等待一段时间后读取缓存
- 示例代码(Python):
import boto3 import time from botocore.exceptions import ClientError dynamodb = boto3.resource('dynamodb') lock_table = dynamodb.Table('AuthorizerLocks') def lambda_handler(event, context): # 从请求中提取唯一用户标识 user_id = event['requestContext']['authorizer']['claims']['sub'] lock_key = f"auth-lock:{user_id}" try: # 尝试获取锁,过期时间设为10秒(根据你的Authorizer执行时间调整) lock_table.put_item( Item={'id': lock_key}, ConditionExpression='attribute_not_exists(id)', Expires=int(time.time()) + 10 ) # 执行权限校验并将结果存入缓存 auth_result = check_user_permissions(user_id) save_auth_result_to_cache(user_id, auth_result) return auth_result except ClientError as e: if e.response['Error']['Code'] == 'ConditionalCheckFailedException': # 锁已存在,等待0.5秒后读取缓存 time.sleep(0.5) return get_auth_result_from_cache(user_id) # 其他异常直接抛出 raise
3. 优化前端请求逻辑
从源头减少并发请求:
- 将同一用户的多个API请求合并为一个批量请求,减少Authorizer调用次数
- 前端实现本地缓存,相同权限校验的请求直接复用之前的授权结果
注意事项
- API Gateway的缓存有1GB上限,用户量较大时要注意缓存密钥的设计,避免出现缓存击穿
- 分布式锁的过期时间要设置合理:既不能太短(否则锁提前失效仍会重复执行),也不能太长(防止Authorizer异常导致锁长期占用)
- 如果使用Cognito等身份服务,可直接利用其JWT缓存特性,减少自定义Authorizer的调用次数
内容的提问来源于stack exchange,提问作者rony yosef
相关产品推荐
相关产品推荐

